From 0df278a2d62d0cfe88d75e5ac74a057b78f66253 Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 19 May 2005 22:05:02 +0000 Subject: [PATCH] bitkeeper revision 1.1476 (428d0d8esmCTqdrDnpEQ1XlfV6CWGg) New qemu-based ioemu for fully virtualised guests. Signed-off-by: Arun Sharma Signed-off-by: Keir Fraser --- .rootkeys | 316 +- tools/Makefile | 20 +- tools/ioemu/COPYING | 339 ++ tools/ioemu/COPYING.LIB | 504 ++ tools/ioemu/Changelog | 295 + tools/ioemu/Makefile | 147 +- tools/ioemu/Makefile.target | 392 ++ tools/ioemu/README | 61 + tools/ioemu/README.distrib | 16 + tools/ioemu/TODO | 66 + tools/ioemu/VERSION | 1 + tools/ioemu/block-cloop.c | 167 + tools/ioemu/block-cow.c | 263 + tools/ioemu/block-qcow.c | 677 +++ tools/ioemu/block-vmdk.c | 279 + tools/ioemu/block.c | 548 ++ tools/ioemu/block_int.h | 77 + tools/ioemu/bswap.h | 202 + tools/ioemu/configure | 585 ++ tools/ioemu/console.c | 731 +++ tools/ioemu/cpu-all.h | 688 +++ tools/ioemu/cpu-defs.h | 95 + tools/ioemu/cpu.h | 69 + tools/ioemu/create_keysym_header.sh | 77 + tools/ioemu/exec-all.h | 579 ++ tools/ioemu/exec.c | 461 ++ tools/ioemu/font/vga.bitmap.h | 288 - tools/ioemu/gui/Makefile | 12 - tools/ioemu/gui/Makefile.in | 561 -- tools/ioemu/gui/bitmaps/cdromd.h | 34 - tools/ioemu/gui/bitmaps/cdromd.xpm | 41 - tools/ioemu/gui/bitmaps/configbutton.h | 16 - tools/ioemu/gui/bitmaps/configbutton.xpm | 41 - tools/ioemu/gui/bitmaps/copy.h | 18 - tools/ioemu/gui/bitmaps/copy.xpm | 41 - tools/ioemu/gui/bitmaps/floppya.h | 34 - tools/ioemu/gui/bitmaps/floppya.xpm | 41 - tools/ioemu/gui/bitmaps/floppyb.h | 34 - tools/ioemu/gui/bitmaps/floppyb.xpm | 41 - tools/ioemu/gui/bitmaps/mouse.h | 34 - tools/ioemu/gui/bitmaps/mouse.xpm | 41 - tools/ioemu/gui/bitmaps/paste.h | 18 - tools/ioemu/gui/bitmaps/paste.xpm | 41 - tools/ioemu/gui/bitmaps/power.h | 20 - tools/ioemu/gui/bitmaps/power.xpm | 41 - tools/ioemu/gui/bitmaps/reset.h | 20 - tools/ioemu/gui/bitmaps/reset.xpm | 41 - tools/ioemu/gui/bitmaps/snapshot.h | 20 - tools/ioemu/gui/bitmaps/snapshot.xpm | 41 - tools/ioemu/gui/bitmaps/userbutton.h | 19 - tools/ioemu/gui/bitmaps/userbutton.xpm | 40 - tools/ioemu/gui/gui.cc | 601 -- tools/ioemu/gui/gui.h | 352 -- tools/ioemu/gui/icon_bochs.h | 40 - tools/ioemu/gui/icon_bochs.xpm | 45 - tools/ioemu/gui/keymap.cc | 330 -- tools/ioemu/gui/keymap.h | 77 - tools/ioemu/gui/keymaps/convertmap.pl | 14 - tools/ioemu/gui/keymaps/sdl-pc-de.map | 222 - tools/ioemu/gui/keymaps/sdl-pc-us.map | 211 - tools/ioemu/gui/keymaps/x11-pc-be.map | 220 - tools/ioemu/gui/keymaps/x11-pc-da.map | 247 - tools/ioemu/gui/keymaps/x11-pc-de.map | 247 - tools/ioemu/gui/keymaps/x11-pc-es.map | 217 - tools/ioemu/gui/keymaps/x11-pc-fr.map | 218 - tools/ioemu/gui/keymaps/x11-pc-it.map | 207 - tools/ioemu/gui/keymaps/x11-pc-se.map | 278 - tools/ioemu/gui/keymaps/x11-pc-uk.map | 209 - tools/ioemu/gui/keymaps/x11-pc-us.map | 205 - tools/ioemu/gui/nogui.cc | 336 -- tools/ioemu/gui/rfb.cc | 1508 ----- tools/ioemu/gui/rfb.h | 35 - tools/ioemu/gui/rfbproto.h | 675 --- tools/ioemu/gui/sdl.h | 1038 ---- tools/ioemu/gui/sdlkeys.h | 257 - tools/ioemu/gui/siminterface.cc | 1411 ----- tools/ioemu/gui/siminterface.h | 1460 ----- tools/ioemu/gui/svga.cc | 514 -- tools/ioemu/gui/term.cc | 843 --- tools/ioemu/gui/textconfig.cc | 995 ---- tools/ioemu/gui/textconfig.h | 19 - tools/ioemu/gui/x.cc | 1848 ------- tools/ioemu/hw/adb.c | 386 ++ tools/ioemu/hw/adlib.c | 313 ++ tools/ioemu/hw/cirrus_vga.c | 3115 +++++++++++ tools/ioemu/hw/cirrus_vga_rop.h | 78 + tools/ioemu/hw/cirrus_vga_rop2.h | 260 + tools/ioemu/hw/cuda.c | 614 +++ tools/ioemu/hw/dma.c | 535 ++ tools/ioemu/hw/fdc.c | 1719 ++++++ tools/ioemu/hw/fmopl.c | 1390 +++++ tools/ioemu/hw/fmopl.h | 174 + tools/ioemu/hw/i8254.c | 505 ++ tools/ioemu/hw/i8259.c | 528 ++ tools/ioemu/hw/ide.c | 2318 ++++++++ tools/ioemu/hw/iommu.c | 218 + tools/ioemu/hw/lance.c | 468 ++ tools/ioemu/hw/m48t08.c | 391 ++ tools/ioemu/hw/m48t08.h | 12 + tools/ioemu/hw/m48t59.c | 602 ++ tools/ioemu/hw/m48t59.h | 13 + tools/ioemu/hw/magic-load.c | 326 ++ tools/ioemu/hw/mc146818rtc.c | 463 ++ tools/ioemu/hw/ne2000.c | 684 +++ tools/ioemu/hw/openpic.c | 1023 ++++ tools/ioemu/hw/pc.c | 575 ++ tools/ioemu/hw/pci.c | 1524 +++++ tools/ioemu/hw/pckbd.c | 919 ++++ tools/ioemu/hw/ppc.c | 462 ++ tools/ioemu/hw/ppc_chrp.c | 233 + tools/ioemu/hw/ppc_prep.c | 548 ++ tools/ioemu/hw/sb16.c | 1268 +++++ tools/ioemu/hw/sched.c | 268 + tools/ioemu/hw/serial.c | 279 + tools/ioemu/hw/sun4m.c | 113 + tools/ioemu/hw/tcx.c | 207 + tools/ioemu/hw/timer.c | 97 + tools/ioemu/hw/vga.c | 2059 +++++++ tools/ioemu/hw/vga_int.h | 168 + tools/ioemu/hw/vga_template.h | 519 ++ tools/ioemu/i386-vl.ld | 140 + tools/ioemu/i386.ld | 140 + tools/ioemu/include/bochs.h | 771 --- tools/ioemu/include/bxversion.h | 7 - tools/ioemu/include/config.h | 919 ---- tools/ioemu/include/cpu/cpu.h | 116 - tools/ioemu/include/extplugin.h | 51 - tools/ioemu/include/instrument.h | 256 - tools/ioemu/include/ltdl.h | 398 -- tools/ioemu/include/ltdlconf.h | 161 - tools/ioemu/include/osdep.h | 176 - tools/ioemu/include/pc_system.h | 226 - tools/ioemu/include/plugin.h | 323 -- tools/ioemu/include/state_file.h | 61 - tools/ioemu/iodev/Makefile | 23 - tools/ioemu/iodev/aspi-win32.h | 210 - tools/ioemu/iodev/biosdev.cc | 212 - tools/ioemu/iodev/biosdev.h | 63 - tools/ioemu/iodev/cdrom.cc | 1338 ----- tools/ioemu/iodev/cdrom.h | 67 - tools/ioemu/iodev/cdrom_beos.h | 10 - tools/ioemu/iodev/cmos.cc | 824 --- tools/ioemu/iodev/cmos.h | 90 - tools/ioemu/iodev/cpu.cc | 358 -- tools/ioemu/iodev/crc32.cc | 49 - tools/ioemu/iodev/crc32.h | 25 - tools/ioemu/iodev/devices.cc | 685 --- tools/ioemu/iodev/dma.cc | 825 --- tools/ioemu/iodev/dma.h | 114 - tools/ioemu/iodev/eth.cc | 194 - tools/ioemu/iodev/eth.h | 76 - tools/ioemu/iodev/eth_arpback.cc | 214 - tools/ioemu/iodev/eth_fbsd.cc | 385 -- tools/ioemu/iodev/eth_linux.cc | 286 - tools/ioemu/iodev/eth_null.cc | 164 - tools/ioemu/iodev/eth_packetmaker.cc | 184 - tools/ioemu/iodev/eth_packetmaker.h | 135 - tools/ioemu/iodev/eth_tap.cc | 370 -- tools/ioemu/iodev/eth_tuntap.cc | 401 -- tools/ioemu/iodev/extfpuirq.cc | 107 - tools/ioemu/iodev/extfpuirq.h | 51 - tools/ioemu/iodev/floppy.cc | 1633 ------ tools/ioemu/iodev/floppy.h | 138 - tools/ioemu/iodev/gameport.cc | 242 - tools/ioemu/iodev/gameport.h | 63 - tools/ioemu/iodev/guest2host.h | 77 - tools/ioemu/iodev/harddrv.cc | 4880 ----------------- tools/ioemu/iodev/harddrv.h | 765 --- tools/ioemu/iodev/ioapic.cc | 175 - tools/ioemu/iodev/ioapic.h | 54 - tools/ioemu/iodev/iodebug.cc | 354 -- tools/ioemu/iodev/iodebug.h | 35 - tools/ioemu/iodev/iodev.h | 422 -- tools/ioemu/iodev/keyboard.cc | 1611 ------ tools/ioemu/iodev/keyboard.h | 234 - tools/ioemu/iodev/load32bitOShack.cc | 322 -- tools/ioemu/iodev/logio.cc | 631 --- tools/ioemu/iodev/main.cc | 4071 -------------- tools/ioemu/iodev/ne2k.cc | 1608 ------ tools/ioemu/iodev/ne2k.h | 239 - tools/ioemu/iodev/osdep.cc | 340 -- tools/ioemu/iodev/parallel.cc | 300 - tools/ioemu/iodev/parallel.h | 78 - tools/ioemu/iodev/pc_system.cc | 570 -- tools/ioemu/iodev/pci.cc | 467 -- tools/ioemu/iodev/pci.h | 90 - tools/ioemu/iodev/pci2isa.cc | 294 - tools/ioemu/iodev/pci2isa.h | 63 - tools/ioemu/iodev/pciusb.cc | 668 --- tools/ioemu/iodev/pciusb.h | 195 - tools/ioemu/iodev/pcivga.cc | 248 - tools/ioemu/iodev/pcivga.h | 48 - tools/ioemu/iodev/pic.cc | 887 --- tools/ioemu/iodev/pic.h | 97 - tools/ioemu/iodev/pit.cc | 856 --- tools/ioemu/iodev/pit.h | 103 - tools/ioemu/iodev/pit82c54.cc | 930 ---- tools/ioemu/iodev/pit82c54.h | 143 - tools/ioemu/iodev/pit_wrap.cc | 444 -- tools/ioemu/iodev/pit_wrap.h | 104 - tools/ioemu/iodev/plugin.cc | 554 -- tools/ioemu/iodev/scancodes.cc | 770 --- tools/ioemu/iodev/scancodes.h | 31 - tools/ioemu/iodev/scsi_commands.h | 418 -- tools/ioemu/iodev/scsidefs.h | 286 - tools/ioemu/iodev/scsipt.h | 144 - tools/ioemu/iodev/serial.cc | 1001 ---- tools/ioemu/iodev/serial.h | 193 - tools/ioemu/iodev/serial_raw.h | 23 - tools/ioemu/iodev/slowdown_timer.cc | 182 - tools/ioemu/iodev/slowdown_timer.h | 33 - tools/ioemu/iodev/soundlnx.cc | 227 - tools/ioemu/iodev/soundlnx.h | 69 - tools/ioemu/iodev/soundwin.cc | 521 -- tools/ioemu/iodev/soundwin.h | 229 - tools/ioemu/iodev/state_file.cc | 136 - tools/ioemu/iodev/unmapped.cc | 305 -- tools/ioemu/iodev/unmapped.h | 64 - tools/ioemu/iodev/vga.cc | 3116 ----------- tools/ioemu/iodev/vga.h | 300 - tools/ioemu/iodev/virt_timer.cc | 552 -- tools/ioemu/iodev/virt_timer.h | 131 - tools/ioemu/keyboard_rdesktop.c | 165 + tools/ioemu/keymaps/ar | 98 + tools/ioemu/keymaps/common | 157 + tools/ioemu/keymaps/convert-map | 63 + tools/ioemu/keymaps/da | 120 + tools/ioemu/keymaps/de | 114 + tools/ioemu/keymaps/de-ch | 169 + tools/ioemu/keymaps/en-gb | 119 + tools/ioemu/keymaps/en-us | 35 + tools/ioemu/keymaps/es | 105 + tools/ioemu/keymaps/et | 86 + tools/ioemu/keymaps/fi | 124 + tools/ioemu/keymaps/fo | 77 + tools/ioemu/keymaps/fr | 181 + tools/ioemu/keymaps/fr-be | 140 + tools/ioemu/keymaps/fr-ca | 50 + tools/ioemu/keymaps/fr-ch | 114 + tools/ioemu/keymaps/hr | 125 + tools/ioemu/keymaps/hu | 115 + tools/ioemu/keymaps/is | 140 + tools/ioemu/keymaps/it | 115 + tools/ioemu/keymaps/ja | 104 + tools/ioemu/keymaps/lt | 57 + tools/ioemu/keymaps/lv | 128 + tools/ioemu/keymaps/mk | 101 + tools/ioemu/keymaps/modifiers | 17 + tools/ioemu/keymaps/nl | 60 + tools/ioemu/keymaps/nl-be | 3 + tools/ioemu/keymaps/no | 119 + tools/ioemu/keymaps/pl | 122 + tools/ioemu/keymaps/pt | 113 + tools/ioemu/keymaps/pt-br | 69 + tools/ioemu/keymaps/ru | 109 + tools/ioemu/keymaps/sl | 110 + tools/ioemu/keymaps/sv | 82 + tools/ioemu/keymaps/th | 131 + tools/ioemu/keymaps/tr | 123 + tools/ioemu/main.c | 250 + tools/ioemu/memory/Makefile | 12 - tools/ioemu/memory/memory.cc | 450 -- tools/ioemu/memory/memory.h | 104 - tools/ioemu/memory/misc_mem.cc | 440 -- tools/ioemu/mk/helix.mk | 6 - tools/ioemu/monitor.c | 282 + tools/ioemu/osdep.c | 499 ++ tools/ioemu/osdep.h | 50 + tools/ioemu/path.c | 147 + tools/ioemu/pc-bios/Makefile | 24 + tools/ioemu/pc-bios/README | 13 + tools/ioemu/pc-bios/bios.bin | Bin 0 -> 65536 bytes tools/ioemu/pc-bios/bios.diff | 162 + tools/ioemu/pc-bios/linux_boot.S | 29 + tools/ioemu/pc-bios/linux_boot.bin | Bin 0 -> 512 bytes tools/ioemu/pc-bios/ppc_rom.bin | Bin 0 -> 524288 bytes tools/ioemu/pc-bios/proll.bin | Bin 0 -> 56856 bytes tools/ioemu/pc-bios/proll.patch | 50 + tools/ioemu/pc-bios/vgabios-cirrus.bin | Bin 0 -> 30868 bytes tools/ioemu/pc-bios/vgabios.bin | Bin 0 -> 31533 bytes tools/ioemu/qemu-binfmt-conf.sh | 34 + tools/ioemu/qemu-doc.html | 1793 ++++++ tools/ioemu/qemu-doc.texi | 1296 +++++ tools/ioemu/qemu-img.c | 698 +++ tools/ioemu/qemu-mkcow.1 | 105 + tools/ioemu/qemu-tech.html | 1303 +++++ tools/ioemu/qemu-tech.texi | 494 ++ tools/ioemu/qemu.1 | 457 ++ tools/ioemu/readline.c | 424 ++ tools/ioemu/sdl.c | 605 ++ tools/ioemu/target-i386-dm/device-model | 69 + tools/ioemu/target-i386-dm/helper2.c | 434 ++ tools/ioemu/target-i386-dm/qemu-ifup | 10 + tools/ioemu/target-i386-dm/qemu-vgaram-bin.gz | Bin 0 -> 3338 bytes tools/ioemu/tests/Makefile | 84 + tools/ioemu/tests/hello-arm.c | 113 + tools/ioemu/tests/hello-i386.c | 26 + tools/ioemu/tests/linux-test.c | 536 ++ tools/ioemu/tests/pi_10.com | Bin 0 -> 54 bytes tools/ioemu/tests/qruncom.c | 308 ++ tools/ioemu/tests/runcom.c | 195 + tools/ioemu/tests/sha1.c | 242 + tools/ioemu/tests/test-i386-code16.S | 97 + tools/ioemu/tests/test-i386-muldiv.h | 56 + tools/ioemu/tests/test-i386-shift.h | 143 + tools/ioemu/tests/test-i386-vm86.S | 104 + tools/ioemu/tests/test-i386.c | 1706 ++++++ tools/ioemu/tests/test-i386.h | 131 + tools/ioemu/tests/test_path.c | 152 + tools/ioemu/tests/testthread.c | 51 + tools/ioemu/texi2pod.pl | 428 ++ tools/ioemu/thunk.c | 243 + tools/ioemu/thunk.h | 158 + tools/ioemu/vgafont.h | 4611 ++++++++++++++++ tools/ioemu/vl.c | 2978 ++++++++++ tools/ioemu/vl.h | 786 +++ tools/ioemu/vnc.c | 501 ++ 317 files changed, 59862 insertions(+), 62342 deletions(-) create mode 100644 tools/ioemu/COPYING create mode 100644 tools/ioemu/COPYING.LIB create mode 100644 tools/ioemu/Changelog create mode 100644 tools/ioemu/Makefile.target create mode 100644 tools/ioemu/README create mode 100644 tools/ioemu/README.distrib create mode 100644 tools/ioemu/TODO create mode 100644 tools/ioemu/VERSION create mode 100644 tools/ioemu/block-cloop.c create mode 100644 tools/ioemu/block-cow.c create mode 100644 tools/ioemu/block-qcow.c create mode 100644 tools/ioemu/block-vmdk.c create mode 100644 tools/ioemu/block.c create mode 100644 tools/ioemu/block_int.h create mode 100644 tools/ioemu/bswap.h create mode 100755 tools/ioemu/configure create mode 100644 tools/ioemu/console.c create mode 100644 tools/ioemu/cpu-all.h create mode 100644 tools/ioemu/cpu-defs.h create mode 100644 tools/ioemu/cpu.h create mode 100644 tools/ioemu/create_keysym_header.sh create mode 100644 tools/ioemu/exec-all.h create mode 100644 tools/ioemu/exec.c delete mode 100644 tools/ioemu/font/vga.bitmap.h delete mode 100644 tools/ioemu/gui/Makefile delete mode 100644 tools/ioemu/gui/Makefile.in delete mode 100644 tools/ioemu/gui/bitmaps/cdromd.h delete mode 100644 tools/ioemu/gui/bitmaps/cdromd.xpm delete mode 100644 tools/ioemu/gui/bitmaps/configbutton.h delete mode 100644 tools/ioemu/gui/bitmaps/configbutton.xpm delete mode 100644 tools/ioemu/gui/bitmaps/copy.h delete mode 100644 tools/ioemu/gui/bitmaps/copy.xpm delete mode 100644 tools/ioemu/gui/bitmaps/floppya.h delete mode 100644 tools/ioemu/gui/bitmaps/floppya.xpm delete mode 100644 tools/ioemu/gui/bitmaps/floppyb.h delete mode 100644 tools/ioemu/gui/bitmaps/floppyb.xpm delete mode 100644 tools/ioemu/gui/bitmaps/mouse.h delete mode 100644 tools/ioemu/gui/bitmaps/mouse.xpm delete mode 100644 tools/ioemu/gui/bitmaps/paste.h delete mode 100644 tools/ioemu/gui/bitmaps/paste.xpm delete mode 100644 tools/ioemu/gui/bitmaps/power.h delete mode 100644 tools/ioemu/gui/bitmaps/power.xpm delete mode 100644 tools/ioemu/gui/bitmaps/reset.h delete mode 100644 tools/ioemu/gui/bitmaps/reset.xpm delete mode 100644 tools/ioemu/gui/bitmaps/snapshot.h delete mode 100644 tools/ioemu/gui/bitmaps/snapshot.xpm delete mode 100644 tools/ioemu/gui/bitmaps/userbutton.h delete mode 100644 tools/ioemu/gui/bitmaps/userbutton.xpm delete mode 100644 tools/ioemu/gui/gui.cc delete mode 100644 tools/ioemu/gui/gui.h delete mode 100644 tools/ioemu/gui/icon_bochs.h delete mode 100644 tools/ioemu/gui/icon_bochs.xpm delete mode 100644 tools/ioemu/gui/keymap.cc delete mode 100644 tools/ioemu/gui/keymap.h delete mode 100644 tools/ioemu/gui/keymaps/convertmap.pl delete mode 100644 tools/ioemu/gui/keymaps/sdl-pc-de.map delete mode 100644 tools/ioemu/gui/keymaps/sdl-pc-us.map delete mode 100644 tools/ioemu/gui/keymaps/x11-pc-be.map delete mode 100644 tools/ioemu/gui/keymaps/x11-pc-da.map delete mode 100644 tools/ioemu/gui/keymaps/x11-pc-de.map delete mode 100644 tools/ioemu/gui/keymaps/x11-pc-es.map delete mode 100644 tools/ioemu/gui/keymaps/x11-pc-fr.map delete mode 100644 tools/ioemu/gui/keymaps/x11-pc-it.map delete mode 100644 tools/ioemu/gui/keymaps/x11-pc-se.map delete mode 100644 tools/ioemu/gui/keymaps/x11-pc-uk.map delete mode 100644 tools/ioemu/gui/keymaps/x11-pc-us.map delete mode 100644 tools/ioemu/gui/nogui.cc delete mode 100644 tools/ioemu/gui/rfb.cc delete mode 100644 tools/ioemu/gui/rfb.h delete mode 100644 tools/ioemu/gui/rfbproto.h delete mode 100644 tools/ioemu/gui/sdl.h delete mode 100644 tools/ioemu/gui/sdlkeys.h delete mode 100644 tools/ioemu/gui/siminterface.cc delete mode 100644 tools/ioemu/gui/siminterface.h delete mode 100644 tools/ioemu/gui/svga.cc delete mode 100644 tools/ioemu/gui/term.cc delete mode 100644 tools/ioemu/gui/textconfig.cc delete mode 100644 tools/ioemu/gui/textconfig.h delete mode 100644 tools/ioemu/gui/x.cc create mode 100644 tools/ioemu/hw/adb.c create mode 100644 tools/ioemu/hw/adlib.c create mode 100644 tools/ioemu/hw/cirrus_vga.c create mode 100644 tools/ioemu/hw/cirrus_vga_rop.h create mode 100644 tools/ioemu/hw/cirrus_vga_rop2.h create mode 100644 tools/ioemu/hw/cuda.c create mode 100644 tools/ioemu/hw/dma.c create mode 100644 tools/ioemu/hw/fdc.c create mode 100644 tools/ioemu/hw/fmopl.c create mode 100644 tools/ioemu/hw/fmopl.h create mode 100644 tools/ioemu/hw/i8254.c create mode 100644 tools/ioemu/hw/i8259.c create mode 100644 tools/ioemu/hw/ide.c create mode 100644 tools/ioemu/hw/iommu.c create mode 100644 tools/ioemu/hw/lance.c create mode 100644 tools/ioemu/hw/m48t08.c create mode 100644 tools/ioemu/hw/m48t08.h create mode 100644 tools/ioemu/hw/m48t59.c create mode 100644 tools/ioemu/hw/m48t59.h create mode 100644 tools/ioemu/hw/magic-load.c create mode 100644 tools/ioemu/hw/mc146818rtc.c create mode 100644 tools/ioemu/hw/ne2000.c create mode 100644 tools/ioemu/hw/openpic.c create mode 100644 tools/ioemu/hw/pc.c create mode 100644 tools/ioemu/hw/pci.c create mode 100644 tools/ioemu/hw/pckbd.c create mode 100644 tools/ioemu/hw/ppc.c create mode 100644 tools/ioemu/hw/ppc_chrp.c create mode 100644 tools/ioemu/hw/ppc_prep.c create mode 100644 tools/ioemu/hw/sb16.c create mode 100644 tools/ioemu/hw/sched.c create mode 100644 tools/ioemu/hw/serial.c create mode 100644 tools/ioemu/hw/sun4m.c create mode 100644 tools/ioemu/hw/tcx.c create mode 100644 tools/ioemu/hw/timer.c create mode 100644 tools/ioemu/hw/vga.c create mode 100644 tools/ioemu/hw/vga_int.h create mode 100644 tools/ioemu/hw/vga_template.h create mode 100644 tools/ioemu/i386-vl.ld create mode 100644 tools/ioemu/i386.ld delete mode 100644 tools/ioemu/include/bochs.h delete mode 100644 tools/ioemu/include/bxversion.h delete mode 100644 tools/ioemu/include/config.h delete mode 100644 tools/ioemu/include/cpu/cpu.h delete mode 100644 tools/ioemu/include/extplugin.h delete mode 100644 tools/ioemu/include/instrument.h delete mode 100644 tools/ioemu/include/ltdl.h delete mode 100644 tools/ioemu/include/ltdlconf.h delete mode 100644 tools/ioemu/include/osdep.h delete mode 100644 tools/ioemu/include/pc_system.h delete mode 100644 tools/ioemu/include/plugin.h delete mode 100644 tools/ioemu/include/state_file.h delete mode 100644 tools/ioemu/iodev/Makefile delete mode 100644 tools/ioemu/iodev/aspi-win32.h delete mode 100644 tools/ioemu/iodev/biosdev.cc delete mode 100644 tools/ioemu/iodev/biosdev.h delete mode 100644 tools/ioemu/iodev/cdrom.cc delete mode 100644 tools/ioemu/iodev/cdrom.h delete mode 100644 tools/ioemu/iodev/cdrom_beos.h delete mode 100644 tools/ioemu/iodev/cmos.cc delete mode 100644 tools/ioemu/iodev/cmos.h delete mode 100644 tools/ioemu/iodev/cpu.cc delete mode 100644 tools/ioemu/iodev/crc32.cc delete mode 100644 tools/ioemu/iodev/crc32.h delete mode 100644 tools/ioemu/iodev/devices.cc delete mode 100644 tools/ioemu/iodev/dma.cc delete mode 100644 tools/ioemu/iodev/dma.h delete mode 100644 tools/ioemu/iodev/eth.cc delete mode 100644 tools/ioemu/iodev/eth.h delete mode 100644 tools/ioemu/iodev/eth_arpback.cc delete mode 100644 tools/ioemu/iodev/eth_fbsd.cc delete mode 100644 tools/ioemu/iodev/eth_linux.cc delete mode 100644 tools/ioemu/iodev/eth_null.cc delete mode 100644 tools/ioemu/iodev/eth_packetmaker.cc delete mode 100644 tools/ioemu/iodev/eth_packetmaker.h delete mode 100644 tools/ioemu/iodev/eth_tap.cc delete mode 100644 tools/ioemu/iodev/eth_tuntap.cc delete mode 100644 tools/ioemu/iodev/extfpuirq.cc delete mode 100644 tools/ioemu/iodev/extfpuirq.h delete mode 100644 tools/ioemu/iodev/floppy.cc delete mode 100644 tools/ioemu/iodev/floppy.h delete mode 100644 tools/ioemu/iodev/gameport.cc delete mode 100644 tools/ioemu/iodev/gameport.h delete mode 100644 tools/ioemu/iodev/guest2host.h delete mode 100644 tools/ioemu/iodev/harddrv.cc delete mode 100644 tools/ioemu/iodev/harddrv.h delete mode 100644 tools/ioemu/iodev/ioapic.cc delete mode 100644 tools/ioemu/iodev/ioapic.h delete mode 100644 tools/ioemu/iodev/iodebug.cc delete mode 100644 tools/ioemu/iodev/iodebug.h delete mode 100644 tools/ioemu/iodev/iodev.h delete mode 100644 tools/ioemu/iodev/keyboard.cc delete mode 100644 tools/ioemu/iodev/keyboard.h delete mode 100644 tools/ioemu/iodev/load32bitOShack.cc delete mode 100644 tools/ioemu/iodev/logio.cc delete mode 100644 tools/ioemu/iodev/main.cc delete mode 100644 tools/ioemu/iodev/ne2k.cc delete mode 100644 tools/ioemu/iodev/ne2k.h delete mode 100644 tools/ioemu/iodev/osdep.cc delete mode 100644 tools/ioemu/iodev/parallel.cc delete mode 100644 tools/ioemu/iodev/parallel.h delete mode 100644 tools/ioemu/iodev/pc_system.cc delete mode 100644 tools/ioemu/iodev/pci.cc delete mode 100644 tools/ioemu/iodev/pci.h delete mode 100644 tools/ioemu/iodev/pci2isa.cc delete mode 100644 tools/ioemu/iodev/pci2isa.h delete mode 100644 tools/ioemu/iodev/pciusb.cc delete mode 100644 tools/ioemu/iodev/pciusb.h delete mode 100644 tools/ioemu/iodev/pcivga.cc delete mode 100644 tools/ioemu/iodev/pcivga.h delete mode 100644 tools/ioemu/iodev/pic.cc delete mode 100644 tools/ioemu/iodev/pic.h delete mode 100644 tools/ioemu/iodev/pit.cc delete mode 100644 tools/ioemu/iodev/pit.h delete mode 100644 tools/ioemu/iodev/pit82c54.cc delete mode 100644 tools/ioemu/iodev/pit82c54.h delete mode 100644 tools/ioemu/iodev/pit_wrap.cc delete mode 100644 tools/ioemu/iodev/pit_wrap.h delete mode 100644 tools/ioemu/iodev/plugin.cc delete mode 100644 tools/ioemu/iodev/scancodes.cc delete mode 100644 tools/ioemu/iodev/scancodes.h delete mode 100644 tools/ioemu/iodev/scsi_commands.h delete mode 100644 tools/ioemu/iodev/scsidefs.h delete mode 100644 tools/ioemu/iodev/scsipt.h delete mode 100644 tools/ioemu/iodev/serial.cc delete mode 100644 tools/ioemu/iodev/serial.h delete mode 100644 tools/ioemu/iodev/serial_raw.h delete mode 100644 tools/ioemu/iodev/slowdown_timer.cc delete mode 100644 tools/ioemu/iodev/slowdown_timer.h delete mode 100644 tools/ioemu/iodev/soundlnx.cc delete mode 100644 tools/ioemu/iodev/soundlnx.h delete mode 100644 tools/ioemu/iodev/soundwin.cc delete mode 100644 tools/ioemu/iodev/soundwin.h delete mode 100644 tools/ioemu/iodev/state_file.cc delete mode 100644 tools/ioemu/iodev/unmapped.cc delete mode 100644 tools/ioemu/iodev/unmapped.h delete mode 100644 tools/ioemu/iodev/vga.cc delete mode 100644 tools/ioemu/iodev/vga.h delete mode 100644 tools/ioemu/iodev/virt_timer.cc delete mode 100644 tools/ioemu/iodev/virt_timer.h create mode 100644 tools/ioemu/keyboard_rdesktop.c create mode 100644 tools/ioemu/keymaps/ar create mode 100644 tools/ioemu/keymaps/common create mode 100644 tools/ioemu/keymaps/convert-map create mode 100644 tools/ioemu/keymaps/da create mode 100644 tools/ioemu/keymaps/de create mode 100644 tools/ioemu/keymaps/de-ch create mode 100644 tools/ioemu/keymaps/en-gb create mode 100644 tools/ioemu/keymaps/en-us create mode 100644 tools/ioemu/keymaps/es create mode 100644 tools/ioemu/keymaps/et create mode 100644 tools/ioemu/keymaps/fi create mode 100644 tools/ioemu/keymaps/fo create mode 100644 tools/ioemu/keymaps/fr create mode 100644 tools/ioemu/keymaps/fr-be create mode 100644 tools/ioemu/keymaps/fr-ca create mode 100644 tools/ioemu/keymaps/fr-ch create mode 100644 tools/ioemu/keymaps/hr create mode 100644 tools/ioemu/keymaps/hu create mode 100644 tools/ioemu/keymaps/is create mode 100644 tools/ioemu/keymaps/it create mode 100644 tools/ioemu/keymaps/ja create mode 100644 tools/ioemu/keymaps/lt create mode 100644 tools/ioemu/keymaps/lv create mode 100644 tools/ioemu/keymaps/mk create mode 100644 tools/ioemu/keymaps/modifiers create mode 100644 tools/ioemu/keymaps/nl create mode 100644 tools/ioemu/keymaps/nl-be create mode 100644 tools/ioemu/keymaps/no create mode 100644 tools/ioemu/keymaps/pl create mode 100644 tools/ioemu/keymaps/pt create mode 100644 tools/ioemu/keymaps/pt-br create mode 100644 tools/ioemu/keymaps/ru create mode 100644 tools/ioemu/keymaps/sl create mode 100644 tools/ioemu/keymaps/sv create mode 100644 tools/ioemu/keymaps/th create mode 100644 tools/ioemu/keymaps/tr create mode 100644 tools/ioemu/main.c delete mode 100644 tools/ioemu/memory/Makefile delete mode 100644 tools/ioemu/memory/memory.cc delete mode 100644 tools/ioemu/memory/memory.h delete mode 100644 tools/ioemu/memory/misc_mem.cc delete mode 100644 tools/ioemu/mk/helix.mk create mode 100644 tools/ioemu/monitor.c create mode 100644 tools/ioemu/osdep.c create mode 100644 tools/ioemu/osdep.h create mode 100644 tools/ioemu/path.c create mode 100644 tools/ioemu/pc-bios/Makefile create mode 100644 tools/ioemu/pc-bios/README create mode 100644 tools/ioemu/pc-bios/bios.bin create mode 100644 tools/ioemu/pc-bios/bios.diff create mode 100644 tools/ioemu/pc-bios/linux_boot.S create mode 100644 tools/ioemu/pc-bios/linux_boot.bin create mode 100644 tools/ioemu/pc-bios/ppc_rom.bin create mode 100644 tools/ioemu/pc-bios/proll.bin create mode 100644 tools/ioemu/pc-bios/proll.patch create mode 100644 tools/ioemu/pc-bios/vgabios-cirrus.bin create mode 100644 tools/ioemu/pc-bios/vgabios.bin create mode 100644 tools/ioemu/qemu-binfmt-conf.sh create mode 100644 tools/ioemu/qemu-doc.html create mode 100644 tools/ioemu/qemu-doc.texi create mode 100644 tools/ioemu/qemu-img.c create mode 100644 tools/ioemu/qemu-mkcow.1 create mode 100644 tools/ioemu/qemu-tech.html create mode 100644 tools/ioemu/qemu-tech.texi create mode 100644 tools/ioemu/qemu.1 create mode 100644 tools/ioemu/readline.c create mode 100644 tools/ioemu/sdl.c create mode 100755 tools/ioemu/target-i386-dm/device-model create mode 100644 tools/ioemu/target-i386-dm/helper2.c create mode 100755 tools/ioemu/target-i386-dm/qemu-ifup create mode 100644 tools/ioemu/target-i386-dm/qemu-vgaram-bin.gz create mode 100644 tools/ioemu/tests/Makefile create mode 100644 tools/ioemu/tests/hello-arm.c create mode 100644 tools/ioemu/tests/hello-i386.c create mode 100644 tools/ioemu/tests/linux-test.c create mode 100644 tools/ioemu/tests/pi_10.com create mode 100644 tools/ioemu/tests/qruncom.c create mode 100644 tools/ioemu/tests/runcom.c create mode 100644 tools/ioemu/tests/sha1.c create mode 100644 tools/ioemu/tests/test-i386-code16.S create mode 100644 tools/ioemu/tests/test-i386-muldiv.h create mode 100644 tools/ioemu/tests/test-i386-shift.h create mode 100644 tools/ioemu/tests/test-i386-vm86.S create mode 100644 tools/ioemu/tests/test-i386.c create mode 100644 tools/ioemu/tests/test-i386.h create mode 100644 tools/ioemu/tests/test_path.c create mode 100644 tools/ioemu/tests/testthread.c create mode 100755 tools/ioemu/texi2pod.pl create mode 100644 tools/ioemu/thunk.c create mode 100644 tools/ioemu/thunk.h create mode 100644 tools/ioemu/vgafont.h create mode 100644 tools/ioemu/vl.c create mode 100644 tools/ioemu/vl.h create mode 100644 tools/ioemu/vnc.c diff --git a/.rootkeys b/.rootkeys index a4eeac0c72..61030860b5 100644 --- a/.rootkeys +++ b/.rootkeys @@ -562,168 +562,160 @@ 4273458dYPghQKVnj_xu5-fC38CcOg tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c 423d3a7b2ENk2IskDZYZ98pe5NsvIA tools/gdb/gdb-6.2.1-xen-sparse/mkbuildtree 423d3a7buANO_q-kgxIRffUu7lMnUw tools/gdb/gdbbuild -41e2ff6dNPgvIrdIF6dC1azdex1U3A tools/ioemu/Makefile -41e2ff6aoF5fgddZi0QpEWqFr89E5g tools/ioemu/font/vga.bitmap.h -41e2ff6avgnBNvZRiL4ynyGGq2UKlw tools/ioemu/gui/Makefile -41e2ff6a30Xuw7pDX3SlVBx3ssOMDQ tools/ioemu/gui/Makefile.in -41e2ff6aGGn5D3-Yh856G7xWJ5ZJsA tools/ioemu/gui/bitmaps/cdromd.h -41e2ff6abNiWU34DwftxJ30sI6TQmw tools/ioemu/gui/bitmaps/cdromd.xpm -41e2ff6adSUYHlvyVpz7q1Izcx5_gQ tools/ioemu/gui/bitmaps/configbutton.h -41e2ff6aLWWXfMqIH2jSCNUzuc4_Yg tools/ioemu/gui/bitmaps/configbutton.xpm -41e2ff6ahsqMjwuhpbqfrFHCBqYhEA tools/ioemu/gui/bitmaps/copy.h -41e2ff6ajL41CnUeGefMrNijudQlCg tools/ioemu/gui/bitmaps/copy.xpm -41e2ff6aXn5GhkDNOGqUcfCLbDZf3w tools/ioemu/gui/bitmaps/floppya.h -41e2ff6agOpnECodSZ62L-Uijy5fsQ tools/ioemu/gui/bitmaps/floppya.xpm -41e2ff6akrHp6jG_Y2BmFpEcaswUqg tools/ioemu/gui/bitmaps/floppyb.h -41e2ff6aGbvPO1cQLMLduGl16rntbg tools/ioemu/gui/bitmaps/floppyb.xpm -41e2ff6aEcsgeBHQZ_5e3rfgo0USMA tools/ioemu/gui/bitmaps/mouse.h -41e2ff6aO8pXESvDVxMG7TgZL7UvFA tools/ioemu/gui/bitmaps/mouse.xpm -41e2ff6aSd1H6Z0dUVUYLsW-6EDrYw tools/ioemu/gui/bitmaps/paste.h -41e2ff6aRGfY6Jd2TThqWtXoh2CHuQ tools/ioemu/gui/bitmaps/paste.xpm -41e2ff6aKDap56ifPVgdBVPc9yfmvw tools/ioemu/gui/bitmaps/power.h -41e2ff6aDLfEO8dFUd9IpsfUpMk-Vg tools/ioemu/gui/bitmaps/power.xpm -41e2ff6aKWtTsWCds4vL2azV3w-XtQ tools/ioemu/gui/bitmaps/reset.h -41e2ff6a_AU4_ytzHU0Btr3trcbVmA tools/ioemu/gui/bitmaps/reset.xpm -41e2ff6a-hGpcXEChJQDo-xRyH5oGQ tools/ioemu/gui/bitmaps/snapshot.h -41e2ff6aRoGi5nKyQFtcUzK0-9dRDA tools/ioemu/gui/bitmaps/snapshot.xpm -41e2ff6aZdTp9lSJjyUI7YoXqQnCng tools/ioemu/gui/bitmaps/userbutton.h -41e2ff6aWc4p23rAKngLMu8eLZiXlw tools/ioemu/gui/bitmaps/userbutton.xpm -41e2ff6a7gMd57Q5DL0kRD-mR7JzZg tools/ioemu/gui/gui.cc -41e2ff6a-USvofVXiSpY76RT4C0IVw tools/ioemu/gui/gui.h -41e2ff6aYAuOb0x4zTVB7cWYIFIdOA tools/ioemu/gui/icon_bochs.h -41e2ff6aZbFf-Djysg393N4vCEJ7ig tools/ioemu/gui/icon_bochs.xpm -41e2ff6ai-vJcSE9hfz4SHZ20rK5QA tools/ioemu/gui/keymap.cc -41e2ff6a_TY9EJnCcbr5EKV_pi90kg tools/ioemu/gui/keymap.h -41e2ff6aP0co3DAK04MrugZCkp0roQ tools/ioemu/gui/keymaps/convertmap.pl -41e2ff6a-GiP9bzqtVXEjxmxiYgzeg tools/ioemu/gui/keymaps/sdl-pc-de.map -41e2ff6aa5xj7jyze5bcPnj-UHYgTQ tools/ioemu/gui/keymaps/sdl-pc-us.map -41e2ff6ahemkf0kG8SzDXq8g2qp9Pg tools/ioemu/gui/keymaps/x11-pc-be.map -41e2ff6ajdaBBS85yriZ3S9ecy5Odg tools/ioemu/gui/keymaps/x11-pc-da.map -41e2ff6aGkLyRvwOTZnDqvobziAoiQ tools/ioemu/gui/keymaps/x11-pc-de.map -41e2ff6aWcqOK6RjpY28Y4bVjMy9yg tools/ioemu/gui/keymaps/x11-pc-es.map -41e2ff6aF46Uu09XOmmkcGDotToSxw tools/ioemu/gui/keymaps/x11-pc-fr.map -41e2ff6aHM040MYLmOeW_PKIx1TWWg tools/ioemu/gui/keymaps/x11-pc-it.map -41e2ff6aCa-6fHjBOoPWP8hDweZ1Fw tools/ioemu/gui/keymaps/x11-pc-se.map -41e2ff6aUH4wvnqRwo91dJBnhxEYUg tools/ioemu/gui/keymaps/x11-pc-uk.map -41e2ff6aF7b08llRJQBLgNAEfyn9wQ tools/ioemu/gui/keymaps/x11-pc-us.map -41e2ff6a2gbWdoaE7X9vtizvQ4QqdQ tools/ioemu/gui/nogui.cc -41e2ff6a_rWAWre2toEtNUMKliCJPA tools/ioemu/gui/rfb.cc -41e2ff6aQfuugiO3YE07l03L6ASP9g tools/ioemu/gui/rfb.h -41e2ff6aTWFzmW0sjxXpQq7ulaj_Pw tools/ioemu/gui/rfbproto.h -41e2ff6bf4pfJkZTN5vA6HbiJJqeNA tools/ioemu/gui/sdl.h -41e2ff6bVnojmIqKJCbhVUKtMcUWJg tools/ioemu/gui/sdlkeys.h -41e2ff6bKVx97oSdGGToXQXvbQgkZA tools/ioemu/gui/siminterface.cc -41e2ff6bDB5XABCVAA7nMolZPe5ZoA tools/ioemu/gui/siminterface.h -41e2ff6benMg1o7HQ2C5PGS3KFHFow tools/ioemu/gui/svga.cc -41e2ff6bz3XZGzzwvXGqFadb3QqWWQ tools/ioemu/gui/term.cc -41e2ff6b8jzKgyKu2gNVlRWepPNA0A tools/ioemu/gui/textconfig.cc -41e2ff6bUKaJhGtIDqUYzAesLg1MGA tools/ioemu/gui/textconfig.h -41e2ff6b__Pd6Q2aYDZ5vB9bGJEMNA tools/ioemu/gui/x.cc -41e2ff6bp96y5NyMIFjH-HpCRcGBPg tools/ioemu/include/bochs.h -41e2ff6bqIMIJlitAnubjNjf70s3dw tools/ioemu/include/bxversion.h -41e2ff6bTfksDlUXSWC_wC_g30r1cQ tools/ioemu/include/config.h -41e2ff6bwDEGCUwYTf1oo9ZCva2nkw tools/ioemu/include/cpu/cpu.h -41e2ff6bH1PTh2iMScpOn9v9R3SDag tools/ioemu/include/extplugin.h -41e2ff6bFS9XP8ndI6IhGFitzsvTtw tools/ioemu/include/instrument.h -41e2ff6bz71jKff_NUdmI279ArbMgw tools/ioemu/include/ltdl.h -41e2ff6bYayW_YSVmb1sJCvk9z9-ug tools/ioemu/include/ltdlconf.h -41e2ff6b_MdkIIjsFYTFMIKIt7Royw tools/ioemu/include/osdep.h -41e2ff6bPJNSITgePniKtvlujrmcLA tools/ioemu/include/pc_system.h -41e2ff6bmHZyZrzF7iHpD212GeAT-w tools/ioemu/include/plugin.h -41e2ff6bHgstm2ZhCIdsag_c3_dVjA tools/ioemu/include/state_file.h -41e2ff6bJjm8-4K6Cu2k6zoanQ8Yyg tools/ioemu/iodev/Makefile -41e2ff6bKj9bQ4ELP2msSYoT7XrxHQ tools/ioemu/iodev/aspi-win32.h -41e2ff6b95DLt3iA-okw7D4NJcaDCg tools/ioemu/iodev/biosdev.cc -41e2ff6b1ra22hFnE6Tm9lxVaH4Mjw tools/ioemu/iodev/biosdev.h -41e2ff6bftET40KQA19RAisCxyDHVQ tools/ioemu/iodev/cdrom.cc -41e2ff6buuSLUZPj9EtlGA3tufslNQ tools/ioemu/iodev/cdrom.h -41e2ff6bvD6jE2JHKP0wd7I_mB7MJg tools/ioemu/iodev/cdrom_beos.h -41e2ff6b99qviTPyKLjy0-D5DIqACw tools/ioemu/iodev/cmos.cc -41e2ff6bpeZbWqQfuwM_Xj-kElElAA tools/ioemu/iodev/cmos.h -41e2ff6bRf7QN_i1c7BAzkQha8AFUg tools/ioemu/iodev/cpu.cc -41e2ff6byVHp6G3fxAlly1u1sx_DEg tools/ioemu/iodev/crc32.cc -41e2ff6bHWz28hOKgLKRizX9UjsyOQ tools/ioemu/iodev/crc32.h -41e2ff6b3tvq7uKSC9DWkOswq0Re8w tools/ioemu/iodev/devices.cc -41e2ff6bO-SYXzx1RB-1If_FNkyjLg tools/ioemu/iodev/dma.cc -41e2ff6bdI7Ri1mVb1MzkvBKlNSx6Q tools/ioemu/iodev/dma.h -41e2ff6bfnGRrb25sneyvOXxSi8pLg tools/ioemu/iodev/eth.cc -41e2ff6bteOXqvNO1FIR5iFHUwqUuA tools/ioemu/iodev/eth.h -41e2ff6bTQxXrfWSsDCISUAdzlAe9w tools/ioemu/iodev/eth_arpback.cc -41e2ff6brorlh9N9Myd1_g7ktKcIfQ tools/ioemu/iodev/eth_fbsd.cc -41e2ff6b5xRFy8_OISEtd2UrHEUdfw tools/ioemu/iodev/eth_linux.cc -41e2ff6biySiByowEn40XP_yx_lxKg tools/ioemu/iodev/eth_null.cc -41e2ff6bFAVD0UO_ob40usJOnEPAZg tools/ioemu/iodev/eth_packetmaker.cc -41e2ff6bsR-mjksFNRC9HiDDVUfI2w tools/ioemu/iodev/eth_packetmaker.h -41e2ff6bMnzZ7cpqVPQY0_0smpqjHw tools/ioemu/iodev/eth_tap.cc -41e2ff6bGa18jj0cqoOAqBPDzk2Aog tools/ioemu/iodev/eth_tuntap.cc -41e2ff6bY1u244mkTGfttym3HoLo5Q tools/ioemu/iodev/extfpuirq.cc -41e2ff6b_wh3dgYBx38KIJ00Qv4XUA tools/ioemu/iodev/extfpuirq.h -41e2ff6b3uiKo02slxJn11bvZKsF3g tools/ioemu/iodev/floppy.cc -41e2ff6bKba0nlJHGy2kWUr_3e_nvw tools/ioemu/iodev/floppy.h -41e2ff6bC1KaCAEBYYTkJJ5_pBydkQ tools/ioemu/iodev/gameport.cc -41e2ff6bePGww4K0p8vTLphdE_zdig tools/ioemu/iodev/gameport.h -41e2ff6biLQpMiiiKokz7qUXpBn5cg tools/ioemu/iodev/guest2host.h -41e2ff6bji1Iix0CzQTeh9yB-Ao14Q tools/ioemu/iodev/harddrv.cc -41e2ff6bcSDALK1SdvKvTCxemzpWwQ tools/ioemu/iodev/harddrv.h -41e2ff6b36hFBfV06tX0a5CRjFpuxA tools/ioemu/iodev/ioapic.cc -41e2ff6brajF6a0a7RkLHiX0M9oH7w tools/ioemu/iodev/ioapic.h -41e2ff6btDX2IfOnC_LkP08ZlKxjJw tools/ioemu/iodev/iodebug.cc -41e2ff6b-__Z4ECo9pHWVM-Rz-0ehw tools/ioemu/iodev/iodebug.h -41e2ff6btRbGfsUt5k4MClieCZ-EBQ tools/ioemu/iodev/iodev.h -41e2ff6bH5C9aG3f2QhoD6zCdShJYQ tools/ioemu/iodev/keyboard.cc -41e2ff6bUOmeloSf5s9Gkdffo1bEyA tools/ioemu/iodev/keyboard.h -41e2ff6b55oybF1yhInYSZX2bxiJSw tools/ioemu/iodev/load32bitOShack.cc -41e2ff6b5WcmfYXaREzUm0KQu7pKCQ tools/ioemu/iodev/logio.cc -41e2ff6bqqHfrDtizlRKA-_oPRbGAw tools/ioemu/iodev/main.cc -41e2ff6cWAAGa6Pt6eE4URbCOq8wQA tools/ioemu/iodev/ne2k.cc -41e2ff6cap6qrVL42AgTpxjav0QMQg tools/ioemu/iodev/ne2k.h -41e2ff6cHH0UoJW74RKZFnPBSt1jUw tools/ioemu/iodev/osdep.cc -41e2ff6ckuFNtxuAQDMVwJtYwL2QCg tools/ioemu/iodev/parallel.cc -41e2ff6cbqWnJwLAQ9NDZJwUyGiIww tools/ioemu/iodev/parallel.h -41e2ff6cAdkxmfzVhbQn9Plq3X4S_w tools/ioemu/iodev/pc_system.cc -41e2ff6csu1e9S_rywWOq9B85IaZzA tools/ioemu/iodev/pci.cc -41e2ff6cjcmNZLD17naGuKj_Qon6Ow tools/ioemu/iodev/pci.h -41e2ff6c91zYiAb9XulXkl2vLERo-w tools/ioemu/iodev/pci2isa.cc -41e2ff6cV7IdLNbFXwlWvdcOz4F1Aw tools/ioemu/iodev/pci2isa.h -41e2ff6cviwF37ZllnYtHA3MEHRMWw tools/ioemu/iodev/pciusb.cc -41e2ff6ceFmfyqr1MgYhEoRM1s6icQ tools/ioemu/iodev/pciusb.h -41e2ff6cd-1VHyISVo789tv3ImNgLw tools/ioemu/iodev/pcivga.cc -41e2ff6cVkXDlrNUTdt7D6BULEp1Tg tools/ioemu/iodev/pcivga.h -41e2ff6c3xjAFB8X5OLFz_8Of62v2Q tools/ioemu/iodev/pic.cc -41e2ff6c4UHzse5_N0Mx6u5dqKrVkw tools/ioemu/iodev/pic.h -41e2ff6cdD9yovRmQNNJu8QVtZg7Iw tools/ioemu/iodev/pit.cc -41e2ff6cXtvewmYJyoxrWGic2sOayg tools/ioemu/iodev/pit.h -41e2ff6cXaqNRxMagdpNiT1kTWJJUA tools/ioemu/iodev/pit82c54.cc -41e2ff6cHAkpKzMwyz3diMZWTswxmg tools/ioemu/iodev/pit82c54.h -41e2ff6cMK9E2gjqHoWV9ZQfz-cP1Q tools/ioemu/iodev/pit_wrap.cc -41e2ff6cbie7fPpQMgBImJ885GAPdw tools/ioemu/iodev/pit_wrap.h -41e2ff6c0wLrWtBHxxboIzHsrZzkRA tools/ioemu/iodev/plugin.cc -41e2ff6cN4Z6pnguPQaqiCkWp42MOQ tools/ioemu/iodev/scancodes.cc -41e2ff6chK1sqb78l1sqhF3fJhjzBw tools/ioemu/iodev/scancodes.h -41e2ff6cIyPvY7hNE5rP_PMZELhyVw tools/ioemu/iodev/scsi_commands.h -41e2ff6cF3wH8A_66_yG92Wk7I2IWQ tools/ioemu/iodev/scsidefs.h -41e2ff6cbAin6eD3Gfz2CozOS4_bwA tools/ioemu/iodev/scsipt.h -41e2ff6cce6mNXZPGmlQ1bg_I0ef8Q tools/ioemu/iodev/serial.cc -41e2ff6cxsITO-ikpd4vBYZUYO3qSw tools/ioemu/iodev/serial.h -41e2ff6cbaCEgMJ92UELiRE2wEYe3g tools/ioemu/iodev/serial_raw.h -41e2ff6cwDKTU8OukKNBNMDiAYUWvQ tools/ioemu/iodev/slowdown_timer.cc -41e2ff6cM5XYdcgL417IBOzW-QipFg tools/ioemu/iodev/slowdown_timer.h -41e2ff6c5X0WxdBPUyZlNmW6Zv_LRQ tools/ioemu/iodev/soundlnx.cc -41e2ff6cIuE1VxGF_L6rdBtD6rZ_aA tools/ioemu/iodev/soundlnx.h -41e2ff6cDIv87LKamP0Y-yjrdqALzQ tools/ioemu/iodev/soundwin.cc -41e2ff6cB55j_uYIqYh-UiLS4wlm_g tools/ioemu/iodev/soundwin.h -41e2ff6dRPBmtxjFbEM5WYuilnSSZg tools/ioemu/iodev/state_file.cc -41e2ff6dMwkI1Dpa-UHSEzHCvjpOyw tools/ioemu/iodev/unmapped.cc -41e2ff6d_yJMFHYPENtVmJz6wyldQA tools/ioemu/iodev/unmapped.h -41e2ff6dU5hJI6Kn70mFingJo4cHUw tools/ioemu/iodev/vga.cc -41e2ff6dh8xDcCXkZzpSqnFP-OXggw tools/ioemu/iodev/vga.h -41e2ff6dayXwb5dxf0K5pd3q4QppRA tools/ioemu/iodev/virt_timer.cc -41e2ff6dI_rNgBwki594UAWN337-zw tools/ioemu/iodev/virt_timer.h -41e2ff6dCCtE_btrlEopLaCsLO3JDA tools/ioemu/memory/Makefile -41e2ff6dZtwsTW8s-Gqv7bqObdvaXw tools/ioemu/memory/memory.cc -41e2ff6dpk6EFzlHlsAsFEFdyG4wrA tools/ioemu/memory/memory.h -41e2ff6d2i-wqgCe4iAXdckUc1GD-A tools/ioemu/memory/misc_mem.cc -41e2ff6dCYuZgf6pxRmphkh5yeuA9Q tools/ioemu/mk/helix.mk +428d0d82yOaUzYQuYQxH7VzQytKo-g tools/ioemu/COPYING +428d0d82EdPp1TqJBembLgyB1y413w tools/ioemu/COPYING.LIB +428d0d82fd6-QydvFfHmeQBGrKnrrA tools/ioemu/Changelog +428d0d82xvTj4yzPYiurazyGj1PaEw tools/ioemu/Makefile +428d0d82dUmXkgIy11G-hoKTkhvkfQ tools/ioemu/Makefile.target +428d0d82HvgRPoyU3f60_u_t1L28Ag tools/ioemu/README +428d0d820gXmfIVHub7p9VbT7bQcMw tools/ioemu/README.distrib +428d0d82aoWewa_6Z5kNUTgkRw0wNg tools/ioemu/TODO +428d0d82WYi8vrG7RKKyIJw01DAnGg tools/ioemu/VERSION +428d0d82wB05ibBxTCSsAhz3qRO7Gg tools/ioemu/block-cloop.c +428d0d82cucBBZFks3aMSL0-C3L9Nw tools/ioemu/block-cow.c +428d0d82s5FM7xmnj1XLAMlt_DdRIA tools/ioemu/block-qcow.c +428d0d83yWYa6mIH2mplo1L_3Cqadw tools/ioemu/block-vmdk.c +428d0d83nfcgHvu37hviRYwAAAAxSQ tools/ioemu/block.c +428d0d83LrXLfgm9h2RPNBRM_vkqsA tools/ioemu/block_int.h +428d0d83zt7CgVsTa-CIorpIGVWe7g tools/ioemu/bswap.h +428d0d83-I9bQJ8EduVO0OmP_YMtVg tools/ioemu/configure +428d0d83sUjdDRZnfykBaWd_uGjVQQ tools/ioemu/console.c +428d0d83Rsv-Pq8iGrvA0ChVTD-KEQ tools/ioemu/cpu-all.h +428d0d830tCm2-QC3iLTo-yS2D7azQ tools/ioemu/cpu-defs.h +428d0d83bOFEAX7Kc_lt7pm_ItnYOg tools/ioemu/cpu.h +428d0d83wJqNCht75GfVfWqGzaDBGA tools/ioemu/create_keysym_header.sh +428d0d83warJp9F3aKU4moRRVfTmFg tools/ioemu/exec-all.h +428d0d83m3Kwp8vJKycK1n5a_LygfA tools/ioemu/exec.c +428d0d83G-F1mvFyzCEMNhiU6ts8lQ tools/ioemu/hw/adb.c +428d0d83EE1hpyfMfr667s4aFK42hg tools/ioemu/hw/adlib.c +428d0d83AoBht7yFAmAUWoi-ZZS2Tw tools/ioemu/hw/cirrus_vga.c +428d0d83lD5ovmJG_Q1VfIIjw1Fm-A tools/ioemu/hw/cirrus_vga_rop.h +428d0d83SCwX65BPgonBcgYCxdKDNA tools/ioemu/hw/cirrus_vga_rop2.h +428d0d83zAKLZ8JX7_D6RMGcml3jRA tools/ioemu/hw/cuda.c +428d0d83OLV-aQor-LfByakKvo-1-g tools/ioemu/hw/dma.c +428d0d83P1VkKtXn90RMN8eBsvPFQA tools/ioemu/hw/fdc.c +428d0d849AqxX6FsPHv0ovjaFyNMVg tools/ioemu/hw/fmopl.c +428d0d84-hHRu7PVXjfc7oLfrDxY6g tools/ioemu/hw/fmopl.h +428d0d84zbtT2C8Xci_SqMP5bZ-wcQ tools/ioemu/hw/i8254.c +428d0d84KlR61OwSzjF0-L4iz58dfQ tools/ioemu/hw/i8259.c +428d0d84auhZx6c5Kv3WrfM2UZvqHA tools/ioemu/hw/ide.c +428d0d84WSlhNzdrcb-f-Lg-W9dniQ tools/ioemu/hw/iommu.c +428d0d84ri8ZtvhB6RJr1YNejjNWIQ tools/ioemu/hw/lance.c +428d0d84cxFFgDv5fBFrlxGoCiy6Nw tools/ioemu/hw/m48t08.c +428d0d84MQYDhAOLnBnag1BZWcW6JA tools/ioemu/hw/m48t08.h +428d0d84sE4ghX33RQ5kDSuyoLdhFg tools/ioemu/hw/m48t59.c +428d0d8465kZWTT4mVgf-VonglDOxw tools/ioemu/hw/m48t59.h +428d0d84OY7tvE-PKrBfjf2vEQXyMA tools/ioemu/hw/magic-load.c +428d0d84U-PYPR_GMVJoQsbCAVAQow tools/ioemu/hw/mc146818rtc.c +428d0d84jtSXGjQYKd_xvSiMM4C_7Q tools/ioemu/hw/ne2000.c +428d0d84SMHPk0cRnrZgUYkMxFXMMQ tools/ioemu/hw/openpic.c +428d0d84lyG0XDg5MxLMSee3MWgq3g tools/ioemu/hw/pc.c +428d0d84HWR3Q7dEESycfJ7hSWdGig tools/ioemu/hw/pci.c +428d0d84Noyn4ik0UX1E7OdfuFdrIw tools/ioemu/hw/pckbd.c +428d0d840SMURRjsz9V96rwt-naynw tools/ioemu/hw/ppc.c +428d0d84MI7kZftH_c0FK1qiiyQBZg tools/ioemu/hw/ppc_chrp.c +428d0d859-xwA89jmzFk6x9UyXjAeA tools/ioemu/hw/ppc_prep.c +428d0d85YS1n4Fr_EK7B01EWSmrYRg tools/ioemu/hw/sb16.c +428d0d85GrUXL_p0ppOUIfWf8--hvw tools/ioemu/hw/sched.c +428d0d85wP3aLdHYJ-hDAImDP2sj_g tools/ioemu/hw/serial.c +428d0d85mOfwFqDCO76K6bc4IQOxQA tools/ioemu/hw/sun4m.c +428d0d852OCpAsfS1PNoJOfnHhFPSQ tools/ioemu/hw/tcx.c +428d0d85gCUCX0nbuRAt28QJgQ5P8w tools/ioemu/hw/timer.c +428d0d85hp-zgN40hVYXWRjhInkUkg tools/ioemu/hw/vga.c +428d0d85G_4S-hpRyrhV4yGjSrS-cQ tools/ioemu/hw/vga_int.h +428d0d85oWl1ONX_gIZWS1fXjeXGlA tools/ioemu/hw/vga_template.h +428d0d85-wAtLF5FYFHCUAxXKNbEkA tools/ioemu/i386-vl.ld +428d0d85d831iQvvCD3LcaOD9rYGkg tools/ioemu/i386.ld +428d0d85_mNnFPE8hnoC3VvBD9CCuA tools/ioemu/keyboard_rdesktop.c +428d0d85SyOIeDg3SoxH2BiBpXWWkA tools/ioemu/keymaps/ar +428d0d85ToGTVvPrl8hKAi2QxCzp2w tools/ioemu/keymaps/common +428d0d85fmdxRplWI5Jp54NNZy5Mmw tools/ioemu/keymaps/convert-map +428d0d85t5IBwlnttPreCS0UX3nbOw tools/ioemu/keymaps/da +428d0d85XRNojuUlkCgvea0I_fdJEg tools/ioemu/keymaps/de +428d0d85QPup3ixECEpa7Pzr9lLEyw tools/ioemu/keymaps/de-ch +428d0d86r5UpNhOSALGJUUDaGv-vnQ tools/ioemu/keymaps/en-gb +428d0d86ylUT-4Skjnwa27vxIeBqYw tools/ioemu/keymaps/en-us +428d0d86vcHusn3XzWTLjKLDdNhZxw tools/ioemu/keymaps/es +428d0d86UVS0Km-9J94RAQM7iAbBzw tools/ioemu/keymaps/et +428d0d86hS47OlX4USgPPWk6RFWKLQ tools/ioemu/keymaps/fi +428d0d86kOcjaVVZqDgV2JDGcXQ8rg tools/ioemu/keymaps/fo +428d0d86c4GgMp1hDU2MFxiZ1Pz9Lg tools/ioemu/keymaps/fr +428d0d86BdbSM5PxuMaSf8vBv6rXQg tools/ioemu/keymaps/fr-be +428d0d86dQk_p9io2QdI9SGC6FVidg tools/ioemu/keymaps/fr-ca +428d0d86JpfLBZmnrv7Yp0tuezgzng tools/ioemu/keymaps/fr-ch +428d0d861RURctgJ3cgtnq0chW6JOA tools/ioemu/keymaps/hr +428d0d86mqzqw70FkLHZFzIkvTJBpw tools/ioemu/keymaps/hu +428d0d86O3ruSBL8ZyRBeLF7Ow67Og tools/ioemu/keymaps/is +428d0d87pcCatuZLYpVWtUu2Da9sgw tools/ioemu/keymaps/it +428d0d87M3Hy7ubCu27ZO-zWDk-YhQ tools/ioemu/keymaps/ja +428d0d87CqrbJBUI28UxJCIduSJ4rQ tools/ioemu/keymaps/lt +428d0d87jIV_V1YwET59i-Py3h0ILA tools/ioemu/keymaps/lv +428d0d87T3KIxrywXSAkRu-AiQQgIQ tools/ioemu/keymaps/mk +428d0d87_wmWi_IBHfpmZzhCKU-Baw tools/ioemu/keymaps/modifiers +428d0d87GgUuEd4Mz9p3mUGkdMdOsg tools/ioemu/keymaps/nl +428d0d87E1NtUwguKl72ifCTjDQ5rQ tools/ioemu/keymaps/nl-be +428d0d87lKhQOfn5yQ0tq3u7hfIgpw tools/ioemu/keymaps/no +428d0d87iD3aff-LOlaA4CmOUVct3Q tools/ioemu/keymaps/pl +428d0d870CMCzI7c6gcGZMNuIYGbnQ tools/ioemu/keymaps/pt +428d0d87gCs2M4A4P1ITzW86lm_-JA tools/ioemu/keymaps/pt-br +428d0d87nzQ8eK1b9_Zs1Z82dOuX1Q tools/ioemu/keymaps/ru +428d0d87uHdsh15a5mAD-HyWni8QDw tools/ioemu/keymaps/sl +428d0d87gsUMIP42oFecYrdZAJDAuw tools/ioemu/keymaps/sv +428d0d87OcfLjKuhg6p2uuiAPvJBqQ tools/ioemu/keymaps/th +428d0d87QbRtHJUft9qBkNXcl4pbzw tools/ioemu/keymaps/tr +428d0d88CJoMejkmBh6pWaqKMvQF8A tools/ioemu/main.c +428d0d88Fcan7gQZ6axXOmokBDLe7g tools/ioemu/monitor.c +428d0d88lVaOC64YBZ1Wzt-WV4JaSw tools/ioemu/osdep.c +428d0d885W7r27CDEJCW6Jlbxggc9g tools/ioemu/osdep.h +428d0d88CiP9tVdIdLWAzOnCOSdafg tools/ioemu/path.c +428d0d88jzHltLAzyhV1lpFckzy8CA tools/ioemu/pc-bios/Makefile +428d0d889pv_iPNBFn6cNRzQfJMC3A tools/ioemu/pc-bios/README +428d0d88mhWW8SQFNfp-NaH3c8QQkg tools/ioemu/pc-bios/bios.bin +428d0d88LMSMDbTFG1-sS8LL90hExw tools/ioemu/pc-bios/bios.diff +428d0d89SHpdZE1S-ywjJCulIWs4Ag tools/ioemu/pc-bios/linux_boot.S +428d0d89hiL0UgU71ero86GEu1loaA tools/ioemu/pc-bios/linux_boot.bin +428d0d894MKpOb385vcoB_s_4q0QOA tools/ioemu/pc-bios/ppc_rom.bin +428d0d896uo6qr-ONYkpleolayT4zw tools/ioemu/pc-bios/proll.bin +428d0d893gsF8AcCadeYXcKM-aqssA tools/ioemu/pc-bios/proll.patch +428d0d89GgbrVx4Ov3Zg-SFX_0BRdw tools/ioemu/pc-bios/vgabios-cirrus.bin +428d0d89h9nqxPIgDpPMXZIWkdosNw tools/ioemu/pc-bios/vgabios.bin +428d0d8908B65zMmhdGVME3jv7gpww tools/ioemu/qemu-binfmt-conf.sh +428d0d89eKfKJmNEURTxLUtIjclvDw tools/ioemu/qemu-doc.html +428d0d89jF9HlGboO7nLco-tqjLJqQ tools/ioemu/qemu-doc.texi +428d0d89taY6NPlnIyOAMQd_Ww5qUw tools/ioemu/qemu-img.c +428d0d89uGqd5VkBf5j3HFIkQMxsNA tools/ioemu/qemu-mkcow.1 +428d0d8941iGGM85zXzn4wSj6zgbQg tools/ioemu/qemu-tech.html +428d0d89IkHVfdVTilpTpxDvOCOiIw tools/ioemu/qemu-tech.texi +428d0d89ME4klwpFGjbiKXQrj2KF7A tools/ioemu/qemu.1 +428d0d89FY-g4UPH-ZW7t5ZCqvQVTQ tools/ioemu/readline.c +428d0d89dLURbktZFufDKSHan01GFg tools/ioemu/sdl.c +428d0d8atdIE_8ACJPPii5_asQNafw tools/ioemu/target-i386-dm/device-model +428d0d8ahpRAYl6s_itBxnTcxyMHaQ tools/ioemu/target-i386-dm/helper2.c +428d0d8aU3Moaq4zNW5QMV_NxD-4XA tools/ioemu/target-i386-dm/qemu-ifup +428d0d8aqidj8n5H2_2qhBV0mIIJzA tools/ioemu/target-i386-dm/qemu-vgaram-bin.gz +428d0d8ahJ-jctJYDXyAMh91-ifrmg tools/ioemu/tests/Makefile +428d0d8ax12h3Jd3Vhw4nh-eG99-iQ tools/ioemu/tests/hello-arm.c +428d0d8acsBcsGQPd0qQllU-4c9fXw tools/ioemu/tests/hello-i386.c +428d0d8aSEf5Q4wB3iaEThUssfFH8w tools/ioemu/tests/linux-test.c +428d0d8a_orWq4Mg5EasDj2l6f4a0w tools/ioemu/tests/pi_10.com +428d0d8aBv9VBjblSU8iAaVojF4qqw tools/ioemu/tests/qruncom.c +428d0d8az-0qSZDA45Mt6y2SdsqF4w tools/ioemu/tests/runcom.c +428d0d8aSf3jnF_aFvwAemDeROZcKQ tools/ioemu/tests/sha1.c +428d0d8aBZGfRZ662SQIuXLdpmih0w tools/ioemu/tests/test-i386-code16.S +428d0d8a8DbLZWzSyVQ_wX1RGr9SVQ tools/ioemu/tests/test-i386-muldiv.h +428d0d8aaMQbnc_vqyQyOcUzyVrXyg tools/ioemu/tests/test-i386-shift.h +428d0d8aKYkFtFSCFHFUivErvx0iqg tools/ioemu/tests/test-i386-vm86.S +428d0d8aHx2CzT77VEsXouep7lZaYQ tools/ioemu/tests/test-i386.c +428d0d8aDSIoqxC4_zr2z8vxMKrmeA tools/ioemu/tests/test-i386.h +428d0d8ajPT5QfGuunOvjNibmURtqQ tools/ioemu/tests/test_path.c +428d0d8bPccWrah4Y_zICBNZ5exhDw tools/ioemu/tests/testthread.c +428d0d8b5F7EB4JnUbdTi_SZvF2wXg tools/ioemu/texi2pod.pl +428d0d8bMq0ZpccpHb1iVvSNbJjRxg tools/ioemu/thunk.c +428d0d8b2PYfwKLLShlnWcM3VWq9ag tools/ioemu/thunk.h +428d0d8bfvbYQwj6MgDr958m4_SfRA tools/ioemu/vgafont.h +428d0d8bgAojEQcAcTV2gj2E_eG4Lw tools/ioemu/vl.c +428d0d8bXiCY4iTjoSPxGry8jXdAtg tools/ioemu/vl.h +428d0d8bQVKedvN5EIPm39s33TXkpA tools/ioemu/vnc.c 3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/libxc/Makefile 41dde8afKYRKxS4XtLv1KUegGQy_bg tools/libxc/linux_boot_params.h 41cc934abX-QLXJXW_clV_wRjM0zYg tools/libxc/plan9a.out.h diff --git a/tools/Makefile b/tools/Makefile index 08a045383d..733f9dc1f5 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -10,30 +10,36 @@ SUBDIRS += xentrace SUBDIRS += python SUBDIRS += xfrd SUBDIRS += xcs -ifndef XEN_NO_IOEMU -SUBDIRS += ioemu -endif SUBDIRS += pygrub -.PHONY: all install clean check check_clean +.PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean + +ifndef XEN_NO_IOEMU +ioemu ioemuinstall ioemuclean: + [ -f ioemu/config-host.h ] || \ + (cd ioemu; ./configure --prefix=$(DESTDIR)/usr) + $(MAKE) -C ioemu $(patsubst ioemu%,%,$@) +else +ioemu ioemuinstall ioemuclean: +endif all: check @set -e; for subdir in $(SUBDIRS); do \ - if [ -f $$subdir/configure ]; then \ - (cd $$subdir; ./configure --prefix=$(DESTDIR)/usr) \ - fi; \ $(MAKE) -C $$subdir $@; \ done + $(MAKE) ioemu install: check @set -e; for subdir in $(SUBDIRS); do \ $(MAKE) -C $$subdir $@; \ done + $(MAKE) ioemuinstall clean: check_clean @set -e; for subdir in $(SUBDIRS); do \ $(MAKE) -C $$subdir $@; \ done + $(MAKE) ioemuclean check: $(MAKE) -C check diff --git a/tools/ioemu/COPYING b/tools/ioemu/COPYING new file mode 100644 index 0000000000..e77696ae8d --- /dev/null +++ b/tools/ioemu/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/tools/ioemu/COPYING.LIB b/tools/ioemu/COPYING.LIB new file mode 100644 index 0000000000..223ede7de3 --- /dev/null +++ b/tools/ioemu/COPYING.LIB @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/tools/ioemu/Changelog b/tools/ioemu/Changelog new file mode 100644 index 0000000000..cebbbc8a36 --- /dev/null +++ b/tools/ioemu/Changelog @@ -0,0 +1,295 @@ +version 0.6.1: + + - Mac OS X port (Pierre d'Herbemont) + - Virtual console support + - Better monitor line edition + - New block device layer + - New 'qcow' growable disk image support with AES encryption and + transparent decompression + - VMware 3 and 4 read-only disk image support (untested) + - Support for up to 4 serial ports + - TFTP server support (Magnus Damm) + - Port redirection support in user mode networking + - Support for not executable data sections + - Compressed loop disk image support (Johannes Schindelin) + - Level triggered IRQ fix (aka NE2000 PCI performance fix) (Steve + Wormley) + - Fixed Fedora Core 2 problems (now you can run qemu without any + LD_ASSUME_KERNEL tricks on FC2) + - DHCP fix for Windows (accept DHCPREQUEST alone) + - SPARC system emulation (Blue Swirl) + - Automatic Samba configuration for host file access from Windows. + - '-loadvm' and '-full-screen' options + - ne2000 savevm support (Johannes Schindelin) + - Ctrl-Alt is now the default grab key. Ctrl-Alt-[0-9] switches to + the virtual consoles. + - BIOS floppy fix for NT4 (Mike Nordell, Derek Fawcus, Volker Ruppert) + - Floppy fixes for NT4 and NT5 (Mike Nordell) + - NT4 IDE fixes (Ben Pfaf, Mike Nordell) + - SDL Audio support and SB16 fixes (malc) + - ENTER instruction bug fix (initial patch by Stefan Kisdaroczi) + - VGA font change fix + - VGA read-only CRTC register fix + +version 0.6.0: + + - minimalist FPU exception support (NetBSD FPU probe fix) + - cr0.ET fix (Win95 boot) + - *BSD port (Markus Niemisto) + - I/O access fix (signaled by Mark Jonckheere) + - IDE drives serial number fix (Mike Nordell) + - int13 CDROM BIOS fix (aka Solaris x86 install CD fix) + - int15, ah=86 BIOS fix (aka Solaris x86 hardware probe hang up fix) + - BSR/BSF "undefined behaviour" fix + - vmdk2raw: convert VMware disk images to raw images + - PCI support + - NE2K PCI support + - dummy VGA PCI support + - VGA font selection fix (Daniel Serpell) + - PIC reset fix (Hidemi KAWAI) + - PIC spurious irq support (aka Solaris install bug) + - added '-localtime' option + - Cirrus CL-GD54xx VGA support (initial patch by Makoto Suzuki (suzu)) + - APM and system shutdown support + - Fixed system reset + - Support for other PC BIOSes + - Initial PowerMac hardware emulation + - PowerMac/PREP OpenFirmware compatible BIOS (Jocelyn Mayer) + - initial IDE BMDMA support (needed for Darwin x86) + - Set the default memory size for PC emulation to 128 MB + +version 0.5.5: + + - SDL full screen support (initial patch by malc) + - VGA support on PowerPC PREP + - VBE fixes (Matthew Mastracci) + - PIT fixes (aka Win98 hardware probe and "VGA slowness" bug) + - IDE master only fixes (aka Win98 CD-ROM probe bug) + - ARM load/store half word fix (Ulrich Hecht) + - FDC fixes for Win98 + +version 0.5.4: + + - qemu-fast fixes + - BIOS area protection fix (aka EMM386.EXE fix) (Mike Nordell) + - keyboard/mouse fix (Mike Nordell) + - IDE fixes (Linux did not recognized slave drivers) + - VM86 EIP masking fix (aka NT5 install fix) (Mike Nordell) + - QEMU can now boot a PowerPC Linux kernel (Jocelyn Mayer) + - User mode network stack + - imul imm8 fix + 0x82 opcode support (Hidemi KAWAI) + - precise self modifying code (aka BeOS install bug) + +version 0.5.3: + + - added Bochs VESA VBE support + - VGA memory map mode 3 access fix (OS/2 install fix) + - IDE fixes (Jens Axboe) + - CPU interrupt fixes + - fixed various TLB invalidation cases (NT install) + - fixed cr0.WP semantics (XP install) + - direct chaining support for SPARC and PowerPC (faster) + - ARM NWFPE support (initial patch by Ulrich Hecht) + - added specific x86 to x86 translator (close to native performance + in qemu-i386 and qemu-fast) + - shm syscalls support (Paul McKerras) + - added accurate CR0.MP/ME/TS emulation + - fixed DMA memory write access (Win95 boot floppy fix) + - graphical x86 linux loader + - command line monitor + - generic removable device support + - support of CD-ROM change + - multiple network interface support + - initial x86-64 host support (Gwenole Beauchesne) + - lret to outer priviledge fix (OS/2 install fix) + - task switch fixes (SkyOS boot) + - VM save/restore commands + - new timer API + - more precise RTC emulation (periodic timers + time updates) + - Win32 port (initial patch by Kazu) + +version 0.5.2: + + - improved soft MMU speed (assembly functions and specializing) + - improved multitasking speed by avoiding flushing TBs when + switching tasks + - improved qemu-fast speed + - improved self modifying code handling (big performance gain in + softmmu mode). + - fixed IO checking + - fixed CD-ROM detection (win98 install CD) + - fixed addseg real mode bug (GRUB boot fix) + - added ROM memory support (win98 boot) + - fixed 'call Ev' in case of paging exception + - updated the script 'qemu-binfmt-conf.sh' to use QEMU automagically + when launching executables for the supported target CPUs. + - PowerPC system emulation update (Jocelyn Mayer) + - PC floppy emulation and DMA fixes (Jocelyn Mayer) + - polled mode for PIC (Jocelyn Mayer) + - fixed PTE dirty bit handling + - fixed xadd same reg bug + - fixed cmpxchg exception safeness + - access to virtual memory in gdb stub + - task gate and NT flag fixes + - eflags optimisation fix for string operations + +version 0.5.1: + + - float access fixes when using soft mmu + - PC emulation support on PowerPC + - A20 support + - IDE CD-ROM emulation + - ARM fixes (Ulrich Hecht) + - SB16 emulation (malc) + - IRET and INT fixes in VM86 mode with IOPL=3 + - Port I/Os use TSS io map + - Full task switching/task gate support + - added verr, verw, arpl, fcmovxx + - PowerPC target support (Jocelyn Mayer) + - Major SPARC target fixes (dynamically linked programs begin to work) + +version 0.5.0: + + - full hardware level VGA emulation + - graphical display with SDL + - added PS/2 mouse and keyboard emulation + - popw (%esp) fix + - mov to/from segment data width fix + - added real mode support + - added Bochs BIOS and LGPL'ed VGA BIOS loader in qemu + - m68k host port (Richard Zidlicky) + - partial soft MMU support for memory mapped I/Os + - multi-target build + - fixed: no error code in hardware interrupts + - fixed: pop ss, mov ss, x and sti disable hardware irqs for the next insn + - correct single stepping thru string operations + - preliminary SPARC target support (Thomas M. Ogrisegg) + - tun-fd option (Rusty Russell) + - automatic IDE geometry detection + - renamed 'vl' to qemu[-fast] and user qemu to qemu-{cpu}. + - added man page + - added full soft mmu mode to launch unpatched OSes. + +version 0.4.3: + + - x86 exception fix in case of nop instruction. + - gcc 3.2.2 bug workaround (RedHat 9 fix) + - sparc and Alpha host fixes + - many ARM target fixes: 'ls' and 'bash' can be launched. + +version 0.4.2: + + - many exception handling fixes (can compile a Linux kernel inside vl) + - IDE emulation support + - initial GDB stub support + - deferred update support for disk images (Rusty Russell) + - accept User Mode Linux Copy On Write disk images + - SMP kernels can at least be booted + +version 0.4.1: + + - more accurate timer support in vl. + - more reliable NE2000 probe in vl. + - added 2.5.66 kernel in vl-test. + - added VLTMPDIR environment variable in vl. + +version 0.4: + + - initial support for ring 0 x86 processor emulation + - fixed signal handling for correct dosemu DPMI emulation + - fast x86 MMU emulation with mmap() + - fixed popl (%esp) case + - Linux kernel can be executed by QEMU with the 'vl' command. + +version 0.3: + + - initial support for ARM emulation + - added fnsave, frstor, fnstenv, fldenv FPU instructions + - added FPU register save in signal emulation + - initial ARM port + - Sparc and Alpha ports work on the regression test + - generic ioctl number conversion + - fixed ioctl type conversion + +version 0.2: + + - PowerPC disassembly and ELF symbols output (Rusty Russell) + - flock support (Rusty Russell) + - ugetrlimit support (Rusty Russell) + - fstat64 fix (Rusty Russell) + - initial Alpha port (Falk Hueffner) + - initial IA64 port (Matt Wilson) + - initial Sparc and Sparc64 port (David S. Miller) + - added HLT instruction + - LRET instruction fix. + - added GPF generation for I/Os. + - added INT3 and TF flag support. + - SHL instruction C flag fix. + - mmap emulation for host page size > 4KB + - self-modifying code support + - better VM86 support (dosemu works on non trivial programs) + - precise exception support (EIP is computed correctly in most cases) + - more precise LDT/GDT/IDT emulation + - faster segment load in vm86 mode + - direct chaining of basic blocks (faster emulation) + +version 0.1.6: + + - automatic library search system. QEMU can now work with unpatched + ELF dynamic loader and libc (Rusty Russell). + - ISO C warning fixes (Alistair Strachan) + - first self-virtualizable version (works only as long as the + translation cache is not flushed) + - RH9 fixes + +version 0.1.5: + + - ppc64 support + personality() patch (Rusty Russell) + - first Alpha CPU patches (Falk Hueffner) + - removed bfd.h dependancy + - fixed shrd, shld, idivl and divl on PowerPC. + - fixed buggy glibc PowerPC rint() function (test-i386 passes now on PowerPC). + +version 0.1.4: + + - more accurate VM86 emulation (can launch small DOS 16 bit + executables in wine). + - fixed push/pop fs/gs + - added iret instruction. + - added times() syscall and SIOCATMARK ioctl. + +version 0.1.3: + + - S390 support (Ulrich Weigand) + - glibc 2.3.x compile fix (Ulrich Weigand) + - socketcall endian fix (Ulrich Weigand) + - struct sockaddr endian fix (Ulrich Weigand) + - sendmsg/recvmsg endian fix (Ulrich Weigand) + - execve endian fix (Ulrich Weigand) + - fdset endian fix (Ulrich Weigand) + - partial setsockopt syscall support (Ulrich Weigand) + - more accurate pushf/popf emulation + - first partial vm86() syscall support (can be used with runcom example). + - added bound, cmpxchg8b, cpuid instructions + - added 16 bit addressing support/override for string operations + - poll() fix + +version 0.1.2: + + - compile fixes + - xlat instruction + - xchg instruction memory lock + - added simple vm86 example (not working with QEMU yet). The 54 byte + DOS executable 'pi_10.com' program was released by Bertram + Felgenhauer (more information at http://www.boo.net/~jasonp/pipage.html). + +version 0.1.1: + + - glibc 2.2 compilation fixes + - added -s and -L options + - binary distribution of x86 glibc and wine + - big endian fixes in ELF loader and getdents. + +version 0.1: + + - initial public release. diff --git a/tools/ioemu/Makefile b/tools/ioemu/Makefile index 24215c5a6f..fc38fde186 100644 --- a/tools/ioemu/Makefile +++ b/tools/ioemu/Makefile @@ -1,19 +1,136 @@ -# Order is important! -SUBDIRS=gui memory iodev +-include config-host.mak -.PHONY: all clean install +CFLAGS=-Wall -O2 -g -fno-strict-aliasing +ifdef CONFIG_DARWIN +CFLAGS+= -mdynamic-no-pic +endif +ifdef CONFIG_WIN32 +CFLAGS+=-fpack-struct +endif +LDFLAGS=-g +LIBS= +DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE +TOOLS=qemu-img +ifdef CONFIG_STATIC +LDFLAGS+=-static +endif +DOCS=qemu-doc.html qemu-tech.html qemu.1 -all: - @for subdir in $(SUBDIRS); do \ - $(MAKE) -C $$subdir $(MAKEDEFS) $@ || exit -1; \ - done +all: $(DOCS) HEADERS + for d in $(TARGET_DIRS); do \ + $(MAKE) -C $$d $@ || exit 1 ; \ + done + +qemu-img: qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c + $(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS) + +dyngen$(EXESUF): dyngen.c + $(HOST_CC) $(CFLAGS) $(DEFINES) -o $@ $^ clean: - @for subdir in $(SUBDIRS); do \ - $(MAKE) -C $$subdir $(MAKEDEFS) $@ || exit -1; \ - done - -install: - @for subdir in $(SUBDIRS); do \ - $(MAKE) -C $$subdir $(MAKEDEFS) $@ || exit -1; \ - done +# avoid old build problems by removing potentially incorrect old files + rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h + rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS qemu.pod *~ */*~ + $(MAKE) -C tests clean + for d in $(TARGET_DIRS); do \ + $(MAKE) -C $$d $@ || exit 1 ; \ + done + +distclean: clean + rm -f config-host.mak config-host.h + rm -f keysym_adapter_sdl.h keysym_adapter_vnc.h + for d in $(TARGET_DIRS); do \ + rm -rf $$d || exit 1 ; \ + done + +KEYMAPS=da en-gb et fr fr-ch is lt modifiers no pt-br sv \ +ar de en-us fi fr-be hr it lv nl pl ru th \ +common de-ch es fo fr-ca hu ja mk nl-be pt sl tr + +install: all + mkdir -p "$(bindir)" +ifndef CONFIG_WIN32 +# install -m 755 -s $(TOOLS) "$(bindir)" +endif + mkdir -p "$(DESTDIR)/$(datadir)" + install -m 644 pc-bios/bios.bin pc-bios/vgabios.bin \ + pc-bios/vgabios-cirrus.bin \ + pc-bios/ppc_rom.bin \ + pc-bios/proll.bin \ + pc-bios/linux_boot.bin "$(DESTDIR)/$(datadir)" + mkdir -p "$(DESTDIR)/$(docdir)" + install -m 644 qemu-doc.html qemu-tech.html "$(DESTDIR)/$(docdir)" +ifndef CONFIG_WIN32 + mkdir -p "$(DESTDIR)/$(mandir)/man1" + install qemu.1 qemu-mkcow.1 "$(DESTDIR)/$(mandir)/man1" + mkdir -p "$(DESTDIR)/$(datadir)/keymaps" + install -m 644 $(addprefix keymaps/,$(KEYMAPS)) "$(DESTDIR)/$(datadir)/keymaps" +endif + for d in $(TARGET_DIRS); do \ + $(MAKE) -C $$d $@ || exit 1 ; \ + done + +# various test targets +test speed test2: all + $(MAKE) -C tests $@ + +TAGS: + etags *.[ch] tests/*.[ch] + +# documentation +%.html: %.texi + texi2html -monolithic -number $< + +qemu.1: qemu-doc.texi + ./texi2pod.pl $< qemu.pod + pod2man --section=1 --center=" " --release=" " qemu.pod > $@ + +FILE=qemu-$(shell cat VERSION) + +# tar release (use 'make -k tar' on a checkouted tree) +tar: + rm -rf /tmp/$(FILE) + cp -r . /tmp/$(FILE) + ( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) --exclude CVS ) + rm -rf /tmp/$(FILE) + +# generate a binary distribution +tarbin: + ( cd $(DESTDIR) ; tar zcvf ~/qemu-$(VERSION)-i386.tar.gz \ + $(DESTDIR)/$(bindir)/qemu $(DESTDIR)/$(bindir)/qemu-fast \ + $(DESTDIR)/$(bindir)/qemu-system-ppc \ + $(DESTDIR)/$(bindir)/qemu-i386 \ + $(DESTDIR)/$(bindir)/qemu-arm \ + $(DESTDIR)/$(bindir)/qemu-sparc \ + $(DESTDIR)/$(bindir)/qemu-ppc \ + $(DESTDIR)/$(datadir)/bios.bin \ + $(DESTDIR)/$(datadir)/vgabios.bin \ + $(DESTDIR)/$(datadir)/vgabios-cirrus.bin \ + $(DESTDIR)/$(datadir)/ppc_rom.bin \ + $(DESTDIR)/$(datadir)/proll.bin \ + $(DESTDIR)/$(datadir)/linux_boot.bin \ + $(DESTDIR)/$(docdir)/qemu-doc.html \ + $(DESTDIR)/$(docdir)/qemu-tech.html \ + $(DESTDIR)/$(mandir)/man1/qemu.1 $(DESTDIR)/$(mandir)/man1/qemu-mkcow.1 ) + +ifneq ($(wildcard .depend),) +include .depend +endif + +HEADERS: + +ifdef CONFIG_SDL +HEADERS: keysym_adapter_sdl.h +endif + +ifdef CONFIG_VNC +HEADERS: keysym_adapter_vnc.h +endif + +keysym_adapter_sdl.h: Makefile create_keysym_header.sh + sh create_keysym_header.sh sdl "$(SDL_CFLAGS)" + +keysym_adapter_vnc.h: Makefile create_keysym_header.sh + sh create_keysym_header.sh vnc "$(VNC_CFLAGS)" + + diff --git a/tools/ioemu/Makefile.target b/tools/ioemu/Makefile.target new file mode 100644 index 0000000000..933e6246a9 --- /dev/null +++ b/tools/ioemu/Makefile.target @@ -0,0 +1,392 @@ +include config.mak + +#assume we directly put qemu code in tools/, same level as bochs dm(ioemu) +XEN_PATH=../../.. +TARGET_PATH=$(SRC_PATH)/target-$(TARGET_ARCH) +VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio +DEFINES=-I. -I$(TARGET_PATH) -I$(SRC_PATH) -I$(XEN_PATH)/xen/include/public +DEFINES+= -I$(XEN_PATH)/tools/libxc +ifdef CONFIG_USER_ONLY +VPATH+=:$(SRC_PATH)/linux-user +DEFINES+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH) +endif +CFLAGS=-Wall -O2 -g -fno-strict-aliasing +LDFLAGS=-g +LIBS= +HELPER_CFLAGS=$(CFLAGS) +DYNGEN=../dyngen$(EXESUF) +# user emulator name +QEMU_USER=qemu-$(TARGET_ARCH) +# system emulator name +ifdef CONFIG_SOFTMMU +ifeq ($(TARGET_ARCH), i386) +QEMU_SYSTEM=qemu$(EXESUF) +else +QEMU_SYSTEM=qemu-system-$(TARGET_ARCH)$(EXESUF) +endif +else +QEMU_SYSTEM=qemu-fast +endif + +QEMU_SYSTEM=qemu-dm +PROGS=$(QEMU_SYSTEM) + +ifdef CONFIG_USER_ONLY +PROGS=$(QEMU_USER) +else +ifeq ($(TARGET_ARCH), i386) + +ifeq ($(ARCH), i386) +PROGS+=$(QEMU_SYSTEM) +ifndef CONFIG_SOFTMMU +CONFIG_STATIC=y +endif +else +# the system emulator using soft mmu is portable +ifdef CONFIG_SOFTMMU +PROGS+=$(QEMU_SYSTEM) +endif +endif # ARCH != i386 + +endif # TARGET_ARCH = i386 + +ifeq ($(TARGET_ARCH), ppc) + +ifeq ($(ARCH), ppc) +PROGS+=$(QEMU_SYSTEM) +endif + +ifeq ($(ARCH), i386) +ifdef CONFIG_SOFTMMU +PROGS+=$(QEMU_SYSTEM) +endif +endif # ARCH = i386 + +ifeq ($(ARCH), amd64) +ifdef CONFIG_SOFTMMU +PROGS+=$(QEMU_SYSTEM) +endif +endif # ARCH = amd64 + +endif # TARGET_ARCH = ppc + +ifeq ($(TARGET_ARCH), sparc) + +ifeq ($(ARCH), ppc) +PROGS+=$(QEMU_SYSTEM) +endif + +ifeq ($(ARCH), i386) +ifdef CONFIG_SOFTMMU +PROGS+=$(QEMU_SYSTEM) +endif +endif # ARCH = i386 + +ifeq ($(ARCH), amd64) +ifdef CONFIG_SOFTMMU +PROGS+=$(QEMU_SYSTEM) +endif +endif # ARCH = amd64 + +endif # TARGET_ARCH = sparc +endif # !CONFIG_USER_ONLY + +ifdef CONFIG_STATIC +LDFLAGS+=-static +endif + +ifeq ($(ARCH),i386) +CFLAGS+=-fomit-frame-pointer +OP_CFLAGS=$(CFLAGS) -mpreferred-stack-boundary=2 +ifeq ($(HAVE_GCC3_OPTIONS),yes) +OP_CFLAGS+= -falign-functions=0 -fno-gcse +else +OP_CFLAGS+= -malign-functions=0 +endif + +ifdef TARGET_GPROF +USE_I386_LD=y +endif +ifdef CONFIG_STATIC +USE_I386_LD=y +endif +ifdef USE_I386_LD +LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386.ld +else +# WARNING: this LDFLAGS is _very_ tricky : qemu is an ELF shared object +# that the kernel ELF loader considers as an executable. I think this +# is the simplest way to make it self virtualizable! +LDFLAGS+=-Wl,-shared +endif +endif + +ifeq ($(ARCH),amd64) +OP_CFLAGS=$(CFLAGS) -falign-functions=0 +LDFLAGS+=-Wl,-T,$(SRC_PATH)/amd64.ld +endif + +ifeq ($(ARCH),ppc) +CFLAGS+= -D__powerpc__ +OP_CFLAGS=$(CFLAGS) +LDFLAGS+=-Wl,-T,$(SRC_PATH)/ppc.ld +endif + +ifeq ($(ARCH),s390) +OP_CFLAGS=$(CFLAGS) +LDFLAGS+=-Wl,-T,$(SRC_PATH)/s390.ld +endif + +ifeq ($(ARCH),sparc) +CFLAGS+=-m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6 +LDFLAGS+=-m32 +OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0 +HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat +# -static is used to avoid g1/g3 usage by the dynamic linker +LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc.ld -static +endif + +ifeq ($(ARCH),sparc64) +CFLAGS+=-m64 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6 +LDFLAGS+=-m64 +OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0 +endif + +ifeq ($(ARCH),alpha) +# -msmall-data is not used because we want two-instruction relocations +# for the constant constructions +OP_CFLAGS=-Wall -O2 -g +# Ensure there's only a single GP +CFLAGS += -msmall-data +LDFLAGS+=-Wl,-T,$(SRC_PATH)/alpha.ld +endif + +ifeq ($(ARCH),ia64) +OP_CFLAGS=$(CFLAGS) +endif + +ifeq ($(ARCH),arm) +OP_CFLAGS=$(CFLAGS) -mno-sched-prolog +LDFLAGS+=-Wl,-T,$(SRC_PATH)/arm.ld +endif + +ifeq ($(ARCH),m68k) +OP_CFLAGS=$(CFLAGS) -fomit-frame-pointer +LDFLAGS+=-Wl,-T,m68k.ld +endif + +ifeq ($(HAVE_GCC3_OPTIONS),yes) +# very important to generate a return at the end of every operation +OP_CFLAGS+=-fno-reorder-blocks -fno-optimize-sibling-calls +endif + +ifeq ($(CONFIG_DARWIN),yes) +OP_CFLAGS+= -mdynamic-no-pic +endif + +######################################################### + +DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE +LIBS+=-lm -L$(XEN_PATH)/dist/install/usr/$(LIBDIR) -lxc -lxutil +ifndef CONFIG_USER_ONLY +LIBS+=-lz +endif +ifdef CONFIG_WIN32 +LIBS+=-lwinmm -lws2_32 -liphlpapi +endif + +# profiling code +ifdef TARGET_GPROF +LDFLAGS+=-p +main.o: CFLAGS+=-p +endif + +OBJS= elfload.o main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o +ifeq ($(TARGET_ARCH), i386) +OBJS+= vm86.o +endif +ifeq ($(TARGET_ARCH), arm) +OBJS+=nwfpe/softfloat.o nwfpe/fpa11.o nwfpe/fpa11_cpdo.o \ +nwfpe/fpa11_cpdt.o nwfpe/fpa11_cprt.o nwfpe/fpopcode.o nwfpe/single_cpdo.o \ + nwfpe/double_cpdo.o nwfpe/extended_cpdo.o +endif +SRCS:= $(OBJS:.o=.c) +OBJS+= libqemu.a + +# cpu emulator library +LIBOBJS= + +ifeq ($(TARGET_ARCH), i386) +LIBOBJS+= helper2.o +ifeq ($(ARCH), i386) +LIBOBJS+=translate-copy.o +endif +endif + +ifeq ($(TARGET_ARCH), ppc) +LIBOBJS+= op_helper.o helper.o +endif + +ifeq ($(TARGET_ARCH), sparc) +LIBOBJS+= op_helper.o helper.o +endif + +all: $(PROGS) + +$(QEMU_USER): $(OBJS) + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) +ifeq ($(ARCH),alpha) +# Mark as 32 bit binary, i. e. it will be mapped into the low 31 bit of +# the address space (31 bit so sign extending doesn't matter) + echo -ne '\001\000\000\000' | dd of=qemu bs=1 seek=48 count=4 conv=notrunc +endif + +# must use static linking to avoid leaving stuff in virtual address space +VL_OBJS=vl.o exec.o monitor.o osdep.o block.o readline.o pci.o console.o +#VL_OBJS+=block-cow.o block-qcow.o block-vmdk.o block-cloop.o +VL_OBJS+= block-cloop.o + +SOUND_HW = sb16.o +AUDIODRV = audio.o noaudio.o wavaudio.o +ifdef CONFIG_SDL +AUDIODRV += sdlaudio.o +endif +ifdef CONFIG_OSS +AUDIODRV += ossaudio.o +endif + +pc.o: DEFINES := -DUSE_SB16 $(DEFINES) + +ifdef CONFIG_ADLIB +SOUND_HW += fmopl.o adlib.o +endif + +ifdef CONFIG_FMOD +AUDIODRV += fmodaudio.o +audio.o fmodaudio.o: DEFINES := -I$(CONFIG_FMOD_INC) $(DEFINES) +LIBS += $(CONFIG_FMOD_LIB) +endif + +# Hardware support +VL_OBJS+= ide.o ne2000.o pckbd.o vga.o dma.o +VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o + +ifeq ($(TARGET_ARCH), ppc) +VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV) +VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o +VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o mixeng.o +endif +ifeq ($(TARGET_ARCH), sparc) +VL_OBJS+= sun4m.o tcx.o lance.o iommu.o sched.o m48t08.o magic-load.o timer.o +endif +ifdef CONFIG_GDBSTUB +VL_OBJS+=gdbstub.o +endif +ifdef CONFIG_VNC +VL_OBJS+=vnc.o +endif +ifdef CONFIG_SDL +VL_OBJS+=sdl.o +endif +ifdef CONFIG_SLIRP +DEFINES+=-I$(SRC_PATH)/slirp +SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \ +slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o \ +tcp_subr.o tcp_timer.o udp.o bootp.o debug.o tftp.o +VL_OBJS+=$(addprefix slirp/, $(SLIRP_OBJS)) +endif + +VL_LDFLAGS= +# specific flags are needed for non soft mmu emulator +ifdef CONFIG_STATIC +VL_LDFLAGS+=-static +endif +ifndef CONFIG_SOFTMMU +VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386-vl.ld +endif +ifndef CONFIG_DARWIN +ifndef CONFIG_WIN32 +VL_LIBS=-lutil +endif +endif + +$(QEMU_SYSTEM): $(VL_OBJS) libqemu.a + $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(VNC_LIBS) $(VL_LIBS) + +vnc.o: vnc.c keyboard_rdesktop.c + $(CC) $(CFLAGS) $(DEFINES) $(VNC_CFLAGS) -c -o $@ $< + +sdl.o: sdl.c keyboard_rdesktop.c + $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $< + +sdlaudio.o: sdlaudio.c + $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $< + +depend: $(SRCS) + $(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend + +# libqemu + +libqemu.a: $(LIBOBJS) + rm -f $@ + $(AR) rcs $@ $(LIBOBJS) + +translate.o: translate.c gen-op.h opc.h cpu.h + +translate-all.o: translate-all.c op.h opc.h cpu.h + +op.h: op.o $(DYNGEN) + $(DYNGEN) -o $@ $< + +opc.h: op.o $(DYNGEN) + $(DYNGEN) -c -o $@ $< + +gen-op.h: op.o $(DYNGEN) + $(DYNGEN) -g -o $@ $< + +op.o: op.c + $(CC) $(OP_CFLAGS) $(DEFINES) -c -o $@ $< + +helper.o: helper.c + $(CC) $(HELPER_CFLAGS) $(DEFINES) -c -o $@ $< + +ifeq ($(TARGET_ARCH), i386) +op.o: op.c opreg_template.h ops_template.h ops_template_mem.h ops_mem.h +endif + +ifeq ($(TARGET_ARCH), arm) +op.o: op.c op_template.h +endif + +ifeq ($(TARGET_ARCH), sparc) +op.o: op.c op_template.h op_mem.h +endif + +ifeq ($(TARGET_ARCH), ppc) +op.o: op.c op_template.h op_mem.h +op_helper.o: op_helper_mem.h +endif + +mixeng.o: mixeng.c mixeng.h mixeng_template.h + +%.o: %.c + $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $< + +%.o: %.S + $(CC) $(DEFINES) -c -o $@ $< + +clean: + rm -rf *.o *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe slirp qemu-vgaram-bin + +install: all + if [ ! -d $(DESTDIR)$(bindir) ];then mkdir -p $(DESTDIR)$(bindir);fi + if [ ! -d $(DESTDIR)$(configdir) ];then mkdir -p $(DESTDIR)$(configdir);fi +ifneq ($(PROGS),) + install -m 755 -s $(PROGS) "$(DESTDIR)$(bindir)" +endif + install -m 755 device-model "$(DESTDIR)$(bindir)" + install -m 755 qemu-ifup "$(DESTDIR)$(configdir)" + gunzip -c qemu-vgaram-bin.gz >qemu-vgaram-bin + install -m 755 qemu-vgaram-bin "$(DESTDIR)$(configdir)" +ifneq ($(wildcard .depend),) +include .depend +endif diff --git a/tools/ioemu/README b/tools/ioemu/README new file mode 100644 index 0000000000..030306717b --- /dev/null +++ b/tools/ioemu/README @@ -0,0 +1,61 @@ +The QEMU x86 emulator +--------------------- + +INSTALLATION +------------ + +Type + + ./configure + make + +to build qemu, qemu-CPU and libqemu.a (CPU is the name of the various +supported target CPUs). + +Type + + make install + +to install QEMU in /usr/local + +Tested tool versions +-------------------- + +In order to compile QEMU succesfully, it is very important that you +have the right tools. The most important one is gcc. I cannot guaranty +that QEMU works if you do not use a tested gcc version. Look at +'configure' and 'Makefile' if you want to make a different gcc +version work. + +host gcc binutils glibc linux distribution +---------------------------------------------------------------------- +x86 2.95.2 2.13.2 2.1.3 2.4.18 + 3.2 2.13.2 2.1.3 2.4.18 + 2.96 2.11.93.0.2 2.2.5 2.4.18 Red Hat 7.3 + 3.2.2 2.13.90.0.18 2.3.2 2.4.20 Red Hat 9 + +PowerPC 3.3 [4] 2.13.90.0.18 2.3.1 2.4.20briq + 3.2 + +Alpha 3.3 [1] 2.14.90.0.4 2.2.5 2.2.20 [2] Debian 3.0 + +Sparc32 2.95.4 2.12.90.0.1 2.2.5 2.4.18 Debian 3.0 + +ARM 2.95.4 2.12.90.0.1 2.2.5 2.4.9 [3] Debian 3.0 + +[1] On Alpha, QEMU needs the gcc 'visibility' attribute only available + for gcc version >= 3.3. +[2] Linux >= 2.4.20 is necessary for precise exception support + (untested). +[3] 2.4.9-ac10-rmk2-np1-cerf2 + +[4] gcc 2.95.x generates invalid code when using too many register +variables. You must use gcc 3.x on PowerPC. + +Documentation +------------- + +Read the documentation in qemu-doc.html. + + +Fabrice Bellard. \ No newline at end of file diff --git a/tools/ioemu/README.distrib b/tools/ioemu/README.distrib new file mode 100644 index 0000000000..a1598a2998 --- /dev/null +++ b/tools/ioemu/README.distrib @@ -0,0 +1,16 @@ +Information about the various packages used to build the current qemu +x86 binary distribution: + +* gcc 2.95.2 was used for the build. A glibc 2.1.3 Debian distribution + was used to get most of the binary packages. + +* wine-20020411 tarball + + ./configure --prefix=/usr/local/wine-i386 + + All exe and libs were stripped. Some compile time tools and the + includes were deleted. + +* ldconfig was launched to build the library links: + + qemu-i386 /usr/gnemul/qemu-i386/bin/ldconfig-i386 -C /usr/gnemul/qemu-i386/etc/ld.so.cache diff --git a/tools/ioemu/TODO b/tools/ioemu/TODO new file mode 100644 index 0000000000..b8e973ce46 --- /dev/null +++ b/tools/ioemu/TODO @@ -0,0 +1,66 @@ +short term: +---------- +- debug option in 'configure' script + disable -fomit-frame-pointer +- Solaris display error with Cirrus VGA + (http://lists.gnu.org/archive/html/qemu-devel/2004-10/msg00390.html). +- Precise VGA timings for old games/demos (malc patch) +- merge PIC spurious interrupt patch +- merge VNC keyboard patch +- merge Solaris patch +- merge ARM patches + self modifying code patch (Paul Brook) +- warning for OS/2: must not use 128 MB memory +- config file (at least for windows/Mac OS X) +- commit message if execution of code in IO memory +- update doc: PCI infos. +- VNC patch + Synaptic patch. +- basic VGA optimizations +- test sysenter/sysexit and fxsr for L4 pistachio 686 +- physical memory cache (reduce qemu-fast address space size to about 32 MB) +- better code fetch (different exception handling + CS.limit support) +- do not resize vga if invalid size. +- avoid looping if only exceptions +- cycle counter for all archs +- TLB code protection support for PPC +- see openMosix Doc +- disable SMC handling for ARM/SPARC/PPC (not finished) +- see undefined flags for BTx insn +- user/kernel PUSHL/POPL in helper.c +- keyboard output buffer filling timing emulation +- return UD exception if LOCK prefix incorrectly used +- test ldt limit < 7 ? +- tests for each target CPU +- fix CCOP optimisation +- fix all remaining thread lock issues (must put TBs in a specific invalid + state, find a solution for tb_flush()). +- fix arm fpu rounding (at least for float->integer conversions) +- SMP support + +ppc specific: +------------ +- TLB invalidate not needed if msr_pr changes +- endianness bugs in do_load_fpscr and do_store_fpscr +- SPR_ENCODE() not useful +- enable shift optimizations ? + +lower priority: +-------------- +- more friendly BIOS (logo) +- int15 ah=86: use better timing +- HDD geometry in CMOS (not used except for very old DOS programs) +- suppress shift_mem ops +- fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret) +- sysenter/sysexit emulation +- optimize FPU operations (evaluate x87 stack pointer statically) +- add IPC syscalls +- use -msoft-float on ARM +- use kernel traps for unaligned accesses on ARM ? +- handle rare page fault cases (in particular if page fault in helpers or + in syscall emulation code). +- fix thread stack freeing (use kernel 2.5.x CLONE_CHILD_CLEARTID) +- more syscalls (in particular all 64 bit ones, IPCs, fix 64 bit + issues, fix 16 bit uid issues) +- use page_unprotect_range in every suitable syscall to handle all + cases of self modifying code. +- use gcc as a backend to generate better code (easy to do by using + op-i386.c operations as local inline functions). +- add SSE2/MMX operations diff --git a/tools/ioemu/VERSION b/tools/ioemu/VERSION new file mode 100644 index 0000000000..7ceb04048e --- /dev/null +++ b/tools/ioemu/VERSION @@ -0,0 +1 @@ +0.6.1 \ No newline at end of file diff --git a/tools/ioemu/block-cloop.c b/tools/ioemu/block-cloop.c new file mode 100644 index 0000000000..f22253daaf --- /dev/null +++ b/tools/ioemu/block-cloop.c @@ -0,0 +1,167 @@ +/* + * QEMU System Emulator block driver + * + * Copyright (c) 2004 Johannes E. Schindelin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" +#include "block_int.h" +#include + +typedef struct BDRVCloopState { + int fd; + uint32_t block_size; + uint32_t n_blocks; + uint64_t* offsets; + uint32_t sectors_per_block; + uint32_t current_block; + char* compressed_block; + char* uncompressed_block; + z_stream zstream; +} BDRVCloopState; + +static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename) +{ + const char* magic_version_2_0="#!/bin/sh\n" + "#V2.0 Format\n" + "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n"; + int length=strlen(magic_version_2_0); + if(length>buf_size) + length=buf_size; + if(!memcmp(magic_version_2_0,buf,length)) + return 2; + return 0; +} + +static int cloop_open(BlockDriverState *bs, const char *filename) +{ + BDRVCloopState *s = bs->opaque; + uint32_t offsets_size,max_compressed_block_size=1,i; + + s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); + if (s->fd < 0) + return -1; + bs->read_only = 1; + + /* read header */ + if(lseek(s->fd,128,SEEK_SET)<0) { +cloop_close: + close(s->fd); + return -1; + } + if(read(s->fd,&s->block_size,4)<4) + goto cloop_close; + s->block_size=be32_to_cpu(s->block_size); + if(read(s->fd,&s->n_blocks,4)<4) + goto cloop_close; + s->n_blocks=be32_to_cpu(s->n_blocks); + + /* read offsets */ + offsets_size=s->n_blocks*sizeof(uint64_t); + if(!(s->offsets=(uint64_t*)malloc(offsets_size))) + goto cloop_close; + if(read(s->fd,s->offsets,offsets_size)n_blocks;i++) { + s->offsets[i]=be64_to_cpu(s->offsets[i]); + if(i>0) { + uint32_t size=s->offsets[i]-s->offsets[i-1]; + if(size>max_compressed_block_size) + max_compressed_block_size=size; + } + } + + /* initialize zlib engine */ + if(!(s->compressed_block=(char*)malloc(max_compressed_block_size+1))) + goto cloop_close; + if(!(s->uncompressed_block=(char*)malloc(s->block_size))) + goto cloop_close; + if(inflateInit(&s->zstream) != Z_OK) + goto cloop_close; + s->current_block=s->n_blocks; + + s->sectors_per_block = s->block_size/512; + bs->total_sectors = s->n_blocks*s->sectors_per_block; + return 0; +} + +static inline int cloop_read_block(BDRVCloopState *s,int block_num) +{ + if(s->current_block != block_num) { + int ret; + uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num]; + + lseek(s->fd, s->offsets[block_num], SEEK_SET); + ret = read(s->fd, s->compressed_block, bytes); + if (ret != bytes) + return -1; + + s->zstream.next_in = s->compressed_block; + s->zstream.avail_in = bytes; + s->zstream.next_out = s->uncompressed_block; + s->zstream.avail_out = s->block_size; + ret = inflateReset(&s->zstream); + if(ret != Z_OK) + return -1; + ret = inflate(&s->zstream, Z_FINISH); + if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size) + return -1; + + s->current_block = block_num; + } + return 0; +} + +static int cloop_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors) +{ + BDRVCloopState *s = bs->opaque; + int i; + + for(i=0;isectors_per_block), + block_num=(sector_num+i)/s->sectors_per_block; + if(cloop_read_block(s, block_num) != 0) + return -1; + memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512); + } + return 0; +} + +static void cloop_close(BlockDriverState *bs) +{ + BDRVCloopState *s = bs->opaque; + close(s->fd); + free(s->compressed_block); + free(s->uncompressed_block); + inflateEnd(&s->zstream); +} + +BlockDriver bdrv_cloop = { + "cloop", + sizeof(BDRVCloopState), + cloop_probe, + cloop_open, + cloop_read, + NULL, + cloop_close, +}; + + diff --git a/tools/ioemu/block-cow.c b/tools/ioemu/block-cow.c new file mode 100644 index 0000000000..81bd334cc1 --- /dev/null +++ b/tools/ioemu/block-cow.c @@ -0,0 +1,263 @@ +/* + * Block driver for the COW format + * + * Copyright (c) 2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef _WIN32 +#include "vl.h" +#include "block_int.h" +#include + +/**************************************************************/ +/* COW block driver using file system holes */ + +/* user mode linux compatible COW file */ +#define COW_MAGIC 0x4f4f4f4d /* MOOO */ +#define COW_VERSION 2 + +struct cow_header_v2 { + uint32_t magic; + uint32_t version; + char backing_file[1024]; + int32_t mtime; + uint64_t size; + uint32_t sectorsize; +}; + +typedef struct BDRVCowState { + int fd; + uint8_t *cow_bitmap; /* if non NULL, COW mappings are used first */ + uint8_t *cow_bitmap_addr; /* mmap address of cow_bitmap */ + int cow_bitmap_size; + int64_t cow_sectors_offset; +} BDRVCowState; + +static int cow_probe(const uint8_t *buf, int buf_size, const char *filename) +{ + const struct cow_header_v2 *cow_header = (const void *)buf; + + if (be32_to_cpu(cow_header->magic) == COW_MAGIC && + be32_to_cpu(cow_header->version) == COW_VERSION) + return 100; + else + return 0; +} + +static int cow_open(BlockDriverState *bs, const char *filename) +{ + BDRVCowState *s = bs->opaque; + int fd; + struct cow_header_v2 cow_header; + int64_t size; + + fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE); + if (fd < 0) { + fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); + if (fd < 0) + return -1; + } + s->fd = fd; + /* see if it is a cow image */ + if (read(fd, &cow_header, sizeof(cow_header)) != sizeof(cow_header)) { + goto fail; + } + + if (be32_to_cpu(cow_header.magic) != COW_MAGIC || + be32_to_cpu(cow_header.version) != COW_VERSION) { + goto fail; + } + + /* cow image found */ + size = be64_to_cpu(cow_header.size); + bs->total_sectors = size / 512; + + pstrcpy(bs->backing_file, sizeof(bs->backing_file), + cow_header.backing_file); + +#if 0 + if (cow_header.backing_file[0] != '\0') { + if (stat(cow_header.backing_file, &st) != 0) { + fprintf(stderr, "%s: could not find original disk image '%s'\n", filename, cow_header.backing_file); + goto fail; + } + if (st.st_mtime != be32_to_cpu(cow_header.mtime)) { + fprintf(stderr, "%s: original raw disk image '%s' does not match saved timestamp\n", filename, cow_header.backing_file); + goto fail; + } + fd = open(cow_header.backing_file, O_RDONLY | O_LARGEFILE); + if (fd < 0) + goto fail; + bs->fd = fd; + } +#endif + /* mmap the bitmap */ + s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header); + s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size), + s->cow_bitmap_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, s->fd, 0); + if (s->cow_bitmap_addr == MAP_FAILED) + goto fail; + s->cow_bitmap = s->cow_bitmap_addr + sizeof(cow_header); + s->cow_sectors_offset = (s->cow_bitmap_size + 511) & ~511; + return 0; + fail: + close(fd); + return -1; +} + +static inline void set_bit(uint8_t *bitmap, int64_t bitnum) +{ + bitmap[bitnum / 8] |= (1 << (bitnum%8)); +} + +static inline int is_bit_set(const uint8_t *bitmap, int64_t bitnum) +{ + return !!(bitmap[bitnum / 8] & (1 << (bitnum%8))); +} + + +/* Return true if first block has been changed (ie. current version is + * in COW file). Set the number of continuous blocks for which that + * is true. */ +static inline int is_changed(uint8_t *bitmap, + int64_t sector_num, int nb_sectors, + int *num_same) +{ + int changed; + + if (!bitmap || nb_sectors == 0) { + *num_same = nb_sectors; + return 0; + } + + changed = is_bit_set(bitmap, sector_num); + for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) { + if (is_bit_set(bitmap, sector_num + *num_same) != changed) + break; + } + + return changed; +} + +static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, int *pnum) +{ + BDRVCowState *s = bs->opaque; + return is_changed(s->cow_bitmap, sector_num, nb_sectors, pnum); +} + +static int cow_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors) +{ + BDRVCowState *s = bs->opaque; + int ret, n; + + while (nb_sectors > 0) { + if (is_changed(s->cow_bitmap, sector_num, nb_sectors, &n)) { + lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET); + ret = read(s->fd, buf, n * 512); + if (ret != n * 512) + return -1; + } else { + memset(buf, 0, n * 512); + } + nb_sectors -= n; + sector_num += n; + buf += n * 512; + } + return 0; +} + +static int cow_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors) +{ + BDRVCowState *s = bs->opaque; + int ret, i; + + lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET); + ret = write(s->fd, buf, nb_sectors * 512); + if (ret != nb_sectors * 512) + return -1; + for (i = 0; i < nb_sectors; i++) + set_bit(s->cow_bitmap, sector_num + i); + return 0; +} + +static void cow_close(BlockDriverState *bs) +{ + BDRVCowState *s = bs->opaque; + munmap(s->cow_bitmap_addr, s->cow_bitmap_size); + close(s->fd); +} + +static int cow_create(const char *filename, int64_t image_sectors, + const char *image_filename, int flags) +{ + int fd, cow_fd; + struct cow_header_v2 cow_header; + struct stat st; + + if (flags) + return -ENOTSUP; + + cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, + 0644); + if (cow_fd < 0) + return -1; + memset(&cow_header, 0, sizeof(cow_header)); + cow_header.magic = cpu_to_be32(COW_MAGIC); + cow_header.version = cpu_to_be32(COW_VERSION); + if (image_filename) { + fd = open(image_filename, O_RDONLY | O_BINARY); + if (fd < 0) { + close(cow_fd); + return -1; + } + if (fstat(fd, &st) != 0) { + close(fd); + return -1; + } + close(fd); + cow_header.mtime = cpu_to_be32(st.st_mtime); + realpath(image_filename, cow_header.backing_file); + } + cow_header.sectorsize = cpu_to_be32(512); + cow_header.size = cpu_to_be64(image_sectors * 512); + write(cow_fd, &cow_header, sizeof(cow_header)); + /* resize to include at least all the bitmap */ + ftruncate(cow_fd, sizeof(cow_header) + ((image_sectors + 7) >> 3)); + close(cow_fd); + return 0; +} + +BlockDriver bdrv_cow = { + "cow", + sizeof(BDRVCowState), + cow_probe, + cow_open, + cow_read, + cow_write, + cow_close, + cow_create, + cow_is_allocated, +}; +#endif diff --git a/tools/ioemu/block-qcow.c b/tools/ioemu/block-qcow.c new file mode 100644 index 0000000000..a473298a82 --- /dev/null +++ b/tools/ioemu/block-qcow.c @@ -0,0 +1,677 @@ +/* + * Block driver for the QCOW format + * + * Copyright (c) 2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" +#include "block_int.h" +#include +#include "aes.h" + +/**************************************************************/ +/* QEMU COW block driver with compression and encryption support */ + +#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb) +#define QCOW_VERSION 1 + +#define QCOW_CRYPT_NONE 0 +#define QCOW_CRYPT_AES 1 + +#define QCOW_OFLAG_COMPRESSED (1LL << 63) + +typedef struct QCowHeader { + uint32_t magic; + uint32_t version; + uint64_t backing_file_offset; + uint32_t backing_file_size; + uint32_t mtime; + uint64_t size; /* in bytes */ + uint8_t cluster_bits; + uint8_t l2_bits; + uint32_t crypt_method; + uint64_t l1_table_offset; +} QCowHeader; + +#define L2_CACHE_SIZE 16 + +typedef struct BDRVQcowState { + int fd; + int cluster_bits; + int cluster_size; + int cluster_sectors; + int l2_bits; + int l2_size; + int l1_size; + uint64_t cluster_offset_mask; + uint64_t l1_table_offset; + uint64_t *l1_table; + uint64_t *l2_cache; + uint64_t l2_cache_offsets[L2_CACHE_SIZE]; + uint32_t l2_cache_counts[L2_CACHE_SIZE]; + uint8_t *cluster_cache; + uint8_t *cluster_data; + uint64_t cluster_cache_offset; + uint32_t crypt_method; /* current crypt method, 0 if no key yet */ + uint32_t crypt_method_header; + AES_KEY aes_encrypt_key; + AES_KEY aes_decrypt_key; +} BDRVQcowState; + +static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset); + +static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename) +{ + const QCowHeader *cow_header = (const void *)buf; + + if (be32_to_cpu(cow_header->magic) == QCOW_MAGIC && + be32_to_cpu(cow_header->version) == QCOW_VERSION) + return 100; + else + return 0; +} + +static int qcow_open(BlockDriverState *bs, const char *filename) +{ + BDRVQcowState *s = bs->opaque; + int fd, len, i, shift; + QCowHeader header; + + fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE); + if (fd < 0) { + fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); + if (fd < 0) + return -1; + } + s->fd = fd; + if (read(fd, &header, sizeof(header)) != sizeof(header)) + goto fail; + be32_to_cpus(&header.magic); + be32_to_cpus(&header.version); + be64_to_cpus(&header.backing_file_offset); + be32_to_cpus(&header.backing_file_size); + be32_to_cpus(&header.mtime); + be64_to_cpus(&header.size); + be32_to_cpus(&header.crypt_method); + be64_to_cpus(&header.l1_table_offset); + + if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION) + goto fail; + if (header.size <= 1 || header.cluster_bits < 9) + goto fail; + if (header.crypt_method > QCOW_CRYPT_AES) + goto fail; + s->crypt_method_header = header.crypt_method; + if (s->crypt_method_header) + bs->encrypted = 1; + s->cluster_bits = header.cluster_bits; + s->cluster_size = 1 << s->cluster_bits; + s->cluster_sectors = 1 << (s->cluster_bits - 9); + s->l2_bits = header.l2_bits; + s->l2_size = 1 << s->l2_bits; + bs->total_sectors = header.size / 512; + s->cluster_offset_mask = (1LL << (63 - s->cluster_bits)) - 1; + + /* read the level 1 table */ + shift = s->cluster_bits + s->l2_bits; + s->l1_size = (header.size + (1LL << shift) - 1) >> shift; + + s->l1_table_offset = header.l1_table_offset; + s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t)); + if (!s->l1_table) + goto fail; + lseek(fd, s->l1_table_offset, SEEK_SET); + if (read(fd, s->l1_table, s->l1_size * sizeof(uint64_t)) != + s->l1_size * sizeof(uint64_t)) + goto fail; + for(i = 0;i < s->l1_size; i++) { + be64_to_cpus(&s->l1_table[i]); + } + /* alloc L2 cache */ + s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t)); + if (!s->l2_cache) + goto fail; + s->cluster_cache = qemu_malloc(s->cluster_size); + if (!s->cluster_cache) + goto fail; + s->cluster_data = qemu_malloc(s->cluster_size); + if (!s->cluster_data) + goto fail; + s->cluster_cache_offset = -1; + + /* read the backing file name */ + if (header.backing_file_offset != 0) { + len = header.backing_file_size; + if (len > 1023) + len = 1023; + lseek(fd, header.backing_file_offset, SEEK_SET); + if (read(fd, bs->backing_file, len) != len) + goto fail; + bs->backing_file[len] = '\0'; + } + return 0; + + fail: + qemu_free(s->l1_table); + qemu_free(s->l2_cache); + qemu_free(s->cluster_cache); + qemu_free(s->cluster_data); + close(fd); + return -1; +} + +static int qcow_set_key(BlockDriverState *bs, const char *key) +{ + BDRVQcowState *s = bs->opaque; + uint8_t keybuf[16]; + int len, i; + + memset(keybuf, 0, 16); + len = strlen(key); + if (len > 16) + len = 16; + /* XXX: we could compress the chars to 7 bits to increase + entropy */ + for(i = 0;i < len;i++) { + keybuf[i] = key[i]; + } + s->crypt_method = s->crypt_method_header; + + if (AES_set_encrypt_key(keybuf, 128, &s->aes_encrypt_key) != 0) + return -1; + if (AES_set_decrypt_key(keybuf, 128, &s->aes_decrypt_key) != 0) + return -1; +#if 0 + /* test */ + { + uint8_t in[16]; + uint8_t out[16]; + uint8_t tmp[16]; + for(i=0;i<16;i++) + in[i] = i; + AES_encrypt(in, tmp, &s->aes_encrypt_key); + AES_decrypt(tmp, out, &s->aes_decrypt_key); + for(i = 0; i < 16; i++) + printf(" %02x", tmp[i]); + printf("\n"); + for(i = 0; i < 16; i++) + printf(" %02x", out[i]); + printf("\n"); + } +#endif + return 0; +} + +/* The crypt function is compatible with the linux cryptoloop + algorithm for < 4 GB images. NOTE: out_buf == in_buf is + supported */ +static void encrypt_sectors(BDRVQcowState *s, int64_t sector_num, + uint8_t *out_buf, const uint8_t *in_buf, + int nb_sectors, int enc, + const AES_KEY *key) +{ + union { + uint64_t ll[2]; + uint8_t b[16]; + } ivec; + int i; + + for(i = 0; i < nb_sectors; i++) { + ivec.ll[0] = cpu_to_le64(sector_num); + ivec.ll[1] = 0; + AES_cbc_encrypt(in_buf, out_buf, 512, key, + ivec.b, enc); + sector_num++; + in_buf += 512; + out_buf += 512; + } +} + +/* 'allocate' is: + * + * 0 to not allocate. + * + * 1 to allocate a normal cluster (for sector indexes 'n_start' to + * 'n_end') + * + * 2 to allocate a compressed cluster of size + * 'compressed_size'. 'compressed_size' must be > 0 and < + * cluster_size + * + * return 0 if not allocated. + */ +static uint64_t get_cluster_offset(BlockDriverState *bs, + uint64_t offset, int allocate, + int compressed_size, + int n_start, int n_end) +{ + BDRVQcowState *s = bs->opaque; + int min_index, i, j, l1_index, l2_index; + uint64_t l2_offset, *l2_table, cluster_offset, tmp; + uint32_t min_count; + int new_l2_table; + + l1_index = offset >> (s->l2_bits + s->cluster_bits); + l2_offset = s->l1_table[l1_index]; + new_l2_table = 0; + if (!l2_offset) { + if (!allocate) + return 0; + /* allocate a new l2 entry */ + l2_offset = lseek(s->fd, 0, SEEK_END); + /* round to cluster size */ + l2_offset = (l2_offset + s->cluster_size - 1) & ~(s->cluster_size - 1); + /* update the L1 entry */ + s->l1_table[l1_index] = l2_offset; + tmp = cpu_to_be64(l2_offset); + lseek(s->fd, s->l1_table_offset + l1_index * sizeof(tmp), SEEK_SET); + if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp)) + return 0; + new_l2_table = 1; + } + for(i = 0; i < L2_CACHE_SIZE; i++) { + if (l2_offset == s->l2_cache_offsets[i]) { + /* increment the hit count */ + if (++s->l2_cache_counts[i] == 0xffffffff) { + for(j = 0; j < L2_CACHE_SIZE; j++) { + s->l2_cache_counts[j] >>= 1; + } + } + l2_table = s->l2_cache + (i << s->l2_bits); + goto found; + } + } + /* not found: load a new entry in the least used one */ + min_index = 0; + min_count = 0xffffffff; + for(i = 0; i < L2_CACHE_SIZE; i++) { + if (s->l2_cache_counts[i] < min_count) { + min_count = s->l2_cache_counts[i]; + min_index = i; + } + } + l2_table = s->l2_cache + (min_index << s->l2_bits); + lseek(s->fd, l2_offset, SEEK_SET); + if (new_l2_table) { + memset(l2_table, 0, s->l2_size * sizeof(uint64_t)); + if (write(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) != + s->l2_size * sizeof(uint64_t)) + return 0; + } else { + if (read(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) != + s->l2_size * sizeof(uint64_t)) + return 0; + } + s->l2_cache_offsets[min_index] = l2_offset; + s->l2_cache_counts[min_index] = 1; + found: + l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1); + cluster_offset = be64_to_cpu(l2_table[l2_index]); + if (!cluster_offset || + ((cluster_offset & QCOW_OFLAG_COMPRESSED) && allocate == 1)) { + if (!allocate) + return 0; + /* allocate a new cluster */ + if ((cluster_offset & QCOW_OFLAG_COMPRESSED) && + (n_end - n_start) < s->cluster_sectors) { + /* if the cluster is already compressed, we must + decompress it in the case it is not completely + overwritten */ + if (decompress_cluster(s, cluster_offset) < 0) + return 0; + cluster_offset = lseek(s->fd, 0, SEEK_END); + cluster_offset = (cluster_offset + s->cluster_size - 1) & + ~(s->cluster_size - 1); + /* write the cluster content */ + lseek(s->fd, cluster_offset, SEEK_SET); + if (write(s->fd, s->cluster_cache, s->cluster_size) != + s->cluster_size) + return -1; + } else { + cluster_offset = lseek(s->fd, 0, SEEK_END); + if (allocate == 1) { + /* round to cluster size */ + cluster_offset = (cluster_offset + s->cluster_size - 1) & + ~(s->cluster_size - 1); + ftruncate(s->fd, cluster_offset + s->cluster_size); + /* if encrypted, we must initialize the cluster + content which won't be written */ + if (s->crypt_method && + (n_end - n_start) < s->cluster_sectors) { + uint64_t start_sect; + start_sect = (offset & ~(s->cluster_size - 1)) >> 9; + memset(s->cluster_data + 512, 0xaa, 512); + for(i = 0; i < s->cluster_sectors; i++) { + if (i < n_start || i >= n_end) { + encrypt_sectors(s, start_sect + i, + s->cluster_data, + s->cluster_data + 512, 1, 1, + &s->aes_encrypt_key); + lseek(s->fd, cluster_offset + i * 512, SEEK_SET); + if (write(s->fd, s->cluster_data, 512) != 512) + return -1; + } + } + } + } else { + cluster_offset |= QCOW_OFLAG_COMPRESSED | + (uint64_t)compressed_size << (63 - s->cluster_bits); + } + } + /* update L2 table */ + tmp = cpu_to_be64(cluster_offset); + l2_table[l2_index] = tmp; + lseek(s->fd, l2_offset + l2_index * sizeof(tmp), SEEK_SET); + if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp)) + return 0; + } + return cluster_offset; +} + +static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, int *pnum) +{ + BDRVQcowState *s = bs->opaque; + int index_in_cluster, n; + uint64_t cluster_offset; + + cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0); + index_in_cluster = sector_num & (s->cluster_sectors - 1); + n = s->cluster_sectors - index_in_cluster; + if (n > nb_sectors) + n = nb_sectors; + *pnum = n; + return (cluster_offset != 0); +} + +static int decompress_buffer(uint8_t *out_buf, int out_buf_size, + const uint8_t *buf, int buf_size) +{ + z_stream strm1, *strm = &strm1; + int ret, out_len; + + memset(strm, 0, sizeof(*strm)); + + strm->next_in = (uint8_t *)buf; + strm->avail_in = buf_size; + strm->next_out = out_buf; + strm->avail_out = out_buf_size; + + ret = inflateInit2(strm, -12); + if (ret != Z_OK) + return -1; + ret = inflate(strm, Z_FINISH); + out_len = strm->next_out - out_buf; + if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) || + out_len != out_buf_size) { + inflateEnd(strm); + return -1; + } + inflateEnd(strm); + return 0; +} + +static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset) +{ + int ret, csize; + uint64_t coffset; + + coffset = cluster_offset & s->cluster_offset_mask; + if (s->cluster_cache_offset != coffset) { + csize = cluster_offset >> (63 - s->cluster_bits); + csize &= (s->cluster_size - 1); + lseek(s->fd, coffset, SEEK_SET); + ret = read(s->fd, s->cluster_data, csize); + if (ret != csize) + return -1; + if (decompress_buffer(s->cluster_cache, s->cluster_size, + s->cluster_data, csize) < 0) { + return -1; + } + s->cluster_cache_offset = coffset; + } + return 0; +} + +static int qcow_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors) +{ + BDRVQcowState *s = bs->opaque; + int ret, index_in_cluster, n; + uint64_t cluster_offset; + + while (nb_sectors > 0) { + cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0); + index_in_cluster = sector_num & (s->cluster_sectors - 1); + n = s->cluster_sectors - index_in_cluster; + if (n > nb_sectors) + n = nb_sectors; + if (!cluster_offset) { + memset(buf, 0, 512 * n); + } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) { + if (decompress_cluster(s, cluster_offset) < 0) + return -1; + memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n); + } else { + lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET); + ret = read(s->fd, buf, n * 512); + if (ret != n * 512) + return -1; + if (s->crypt_method) { + encrypt_sectors(s, sector_num, buf, buf, n, 0, + &s->aes_decrypt_key); + } + } + nb_sectors -= n; + sector_num += n; + buf += n * 512; + } + return 0; +} + +static int qcow_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors) +{ + BDRVQcowState *s = bs->opaque; + int ret, index_in_cluster, n; + uint64_t cluster_offset; + + while (nb_sectors > 0) { + index_in_cluster = sector_num & (s->cluster_sectors - 1); + n = s->cluster_sectors - index_in_cluster; + if (n > nb_sectors) + n = nb_sectors; + cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0, + index_in_cluster, + index_in_cluster + n); + if (!cluster_offset) + return -1; + lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET); + if (s->crypt_method) { + encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1, + &s->aes_encrypt_key); + ret = write(s->fd, s->cluster_data, n * 512); + } else { + ret = write(s->fd, buf, n * 512); + } + if (ret != n * 512) + return -1; + nb_sectors -= n; + sector_num += n; + buf += n * 512; + } + s->cluster_cache_offset = -1; /* disable compressed cache */ + return 0; +} + +static void qcow_close(BlockDriverState *bs) +{ + BDRVQcowState *s = bs->opaque; + qemu_free(s->l1_table); + qemu_free(s->l2_cache); + qemu_free(s->cluster_cache); + qemu_free(s->cluster_data); + close(s->fd); +} + +static int qcow_create(const char *filename, int64_t total_size, + const char *backing_file, int flags) +{ + int fd, header_size, backing_filename_len, l1_size, i, shift; + QCowHeader header; + char backing_filename[1024]; + uint64_t tmp; + struct stat st; + + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, + 0644); + if (fd < 0) + return -1; + memset(&header, 0, sizeof(header)); + header.magic = cpu_to_be32(QCOW_MAGIC); + header.version = cpu_to_be32(QCOW_VERSION); + header.size = cpu_to_be64(total_size * 512); + header_size = sizeof(header); + backing_filename_len = 0; + if (backing_file) { + realpath(backing_file, backing_filename); + if (stat(backing_filename, &st) != 0) { + return -1; + } + header.mtime = cpu_to_be32(st.st_mtime); + header.backing_file_offset = cpu_to_be64(header_size); + backing_filename_len = strlen(backing_filename); + header.backing_file_size = cpu_to_be32(backing_filename_len); + header_size += backing_filename_len; + header.cluster_bits = 9; /* 512 byte cluster to avoid copying + unmodifyed sectors */ + header.l2_bits = 12; /* 32 KB L2 tables */ + } else { + header.cluster_bits = 12; /* 4 KB clusters */ + header.l2_bits = 9; /* 4 KB L2 tables */ + } + header_size = (header_size + 7) & ~7; + shift = header.cluster_bits + header.l2_bits; + l1_size = ((total_size * 512) + (1LL << shift) - 1) >> shift; + + header.l1_table_offset = cpu_to_be64(header_size); + if (flags) { + header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES); + } else { + header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE); + } + + /* write all the data */ + write(fd, &header, sizeof(header)); + if (backing_file) { + write(fd, backing_filename, backing_filename_len); + } + lseek(fd, header_size, SEEK_SET); + tmp = 0; + for(i = 0;i < l1_size; i++) { + write(fd, &tmp, sizeof(tmp)); + } + close(fd); + return 0; +} + +int qcow_get_cluster_size(BlockDriverState *bs) +{ + BDRVQcowState *s = bs->opaque; + if (bs->drv != &bdrv_qcow) + return -1; + return s->cluster_size; +} + +/* XXX: put compressed sectors first, then all the cluster aligned + tables to avoid losing bytes in alignment */ +int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf) +{ + BDRVQcowState *s = bs->opaque; + z_stream strm; + int ret, out_len; + uint8_t *out_buf; + uint64_t cluster_offset; + + if (bs->drv != &bdrv_qcow) + return -1; + + out_buf = qemu_malloc(s->cluster_size + (s->cluster_size / 1000) + 128); + if (!out_buf) + return -1; + + /* best compression, small window, no zlib header */ + memset(&strm, 0, sizeof(strm)); + ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, + Z_DEFLATED, -12, + 9, Z_DEFAULT_STRATEGY); + if (ret != 0) { + qemu_free(out_buf); + return -1; + } + + strm.avail_in = s->cluster_size; + strm.next_in = (uint8_t *)buf; + strm.avail_out = s->cluster_size; + strm.next_out = out_buf; + + ret = deflate(&strm, Z_FINISH); + if (ret != Z_STREAM_END && ret != Z_OK) { + qemu_free(out_buf); + deflateEnd(&strm); + return -1; + } + out_len = strm.next_out - out_buf; + + deflateEnd(&strm); + + if (ret != Z_STREAM_END || out_len >= s->cluster_size) { + /* could not compress: write normal cluster */ + qcow_write(bs, sector_num, buf, s->cluster_sectors); + } else { + cluster_offset = get_cluster_offset(bs, sector_num << 9, 2, + out_len, 0, 0); + cluster_offset &= s->cluster_offset_mask; + lseek(s->fd, cluster_offset, SEEK_SET); + if (write(s->fd, out_buf, out_len) != out_len) { + qemu_free(out_buf); + return -1; + } + } + + qemu_free(out_buf); + return 0; +} + +BlockDriver bdrv_qcow = { + "qcow", + sizeof(BDRVQcowState), + qcow_probe, + qcow_open, + qcow_read, + qcow_write, + qcow_close, + qcow_create, + qcow_is_allocated, + qcow_set_key, +}; + + diff --git a/tools/ioemu/block-vmdk.c b/tools/ioemu/block-vmdk.c new file mode 100644 index 0000000000..1cc4988534 --- /dev/null +++ b/tools/ioemu/block-vmdk.c @@ -0,0 +1,279 @@ +/* + * Block driver for the VMDK format + * + * Copyright (c) 2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" +#include "block_int.h" + +/* XXX: this code is untested */ +/* XXX: add write support */ + +#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D') +#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V') + +typedef struct { + uint32_t version; + uint32_t flags; + uint32_t disk_sectors; + uint32_t granularity; + uint32_t l1dir_offset; + uint32_t l1dir_size; + uint32_t file_sectors; + uint32_t cylinders; + uint32_t heads; + uint32_t sectors_per_track; +} VMDK3Header; + +typedef struct { + uint32_t version; + uint32_t flags; + int64_t capacity; + int64_t granularity; + int64_t desc_offset; + int64_t desc_size; + int32_t num_gtes_per_gte; + int64_t rgd_offset; + int64_t gd_offset; + int64_t grain_offset; + char filler[1]; + char check_bytes[4]; +} VMDK4Header; + +#define L2_CACHE_SIZE 16 + +typedef struct BDRVVmdkState { + int fd; + int64_t l1_table_offset; + uint32_t *l1_table; + unsigned int l1_size; + uint32_t l1_entry_sectors; + + unsigned int l2_size; + uint32_t *l2_cache; + uint32_t l2_cache_offsets[L2_CACHE_SIZE]; + uint32_t l2_cache_counts[L2_CACHE_SIZE]; + + unsigned int cluster_sectors; +} BDRVVmdkState; + +static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename) +{ + uint32_t magic; + + if (buf_size < 4) + return 0; + magic = be32_to_cpu(*(uint32_t *)buf); + if (magic == VMDK3_MAGIC || + magic == VMDK4_MAGIC) + return 100; + else + return 0; +} + +static int vmdk_open(BlockDriverState *bs, const char *filename) +{ + BDRVVmdkState *s = bs->opaque; + int fd, i; + uint32_t magic; + int l1_size; + + fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); + if (fd < 0) + return -1; + if (read(fd, &magic, sizeof(magic)) != sizeof(magic)) + goto fail; + magic = be32_to_cpu(magic); + if (magic == VMDK3_MAGIC) { + VMDK3Header header; + if (read(fd, &header, sizeof(header)) != + sizeof(header)) + goto fail; + s->cluster_sectors = le32_to_cpu(header.granularity); + s->l2_size = 1 << 9; + s->l1_size = 1 << 6; + bs->total_sectors = le32_to_cpu(header.disk_sectors); + s->l1_table_offset = le32_to_cpu(header.l1dir_offset) * 512; + s->l1_entry_sectors = s->l2_size * s->cluster_sectors; + } else if (magic == VMDK4_MAGIC) { + VMDK4Header header; + + if (read(fd, &header, sizeof(header)) != sizeof(header)) + goto fail; + bs->total_sectors = le32_to_cpu(header.capacity); + s->cluster_sectors = le32_to_cpu(header.granularity); + s->l2_size = le32_to_cpu(header.num_gtes_per_gte); + s->l1_entry_sectors = s->l2_size * s->cluster_sectors; + if (s->l1_entry_sectors <= 0) + goto fail; + s->l1_size = (bs->total_sectors + s->l1_entry_sectors - 1) + / s->l1_entry_sectors; + s->l1_table_offset = le64_to_cpu(header.rgd_offset) * 512; + } else { + goto fail; + } + /* read the L1 table */ + l1_size = s->l1_size * sizeof(uint32_t); + s->l1_table = qemu_malloc(l1_size); + if (!s->l1_table) + goto fail; + if (lseek(fd, s->l1_table_offset, SEEK_SET) == -1) + goto fail; + if (read(fd, s->l1_table, l1_size) != l1_size) + goto fail; + for(i = 0; i < s->l1_size; i++) { + le32_to_cpus(&s->l1_table[i]); + } + + s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t)); + if (!s->l2_cache) + goto fail; + s->fd = fd; + /* XXX: currently only read only */ + bs->read_only = 1; + return 0; + fail: + qemu_free(s->l1_table); + qemu_free(s->l2_cache); + close(fd); + return -1; +} + +static uint64_t get_cluster_offset(BlockDriverState *bs, + uint64_t offset) +{ + BDRVVmdkState *s = bs->opaque; + unsigned int l1_index, l2_offset, l2_index; + int min_index, i, j; + uint32_t min_count, *l2_table; + uint64_t cluster_offset; + + l1_index = (offset >> 9) / s->l1_entry_sectors; + if (l1_index >= s->l1_size) + return 0; + l2_offset = s->l1_table[l1_index]; + if (!l2_offset) + return 0; + + for(i = 0; i < L2_CACHE_SIZE; i++) { + if (l2_offset == s->l2_cache_offsets[i]) { + /* increment the hit count */ + if (++s->l2_cache_counts[i] == 0xffffffff) { + for(j = 0; j < L2_CACHE_SIZE; j++) { + s->l2_cache_counts[j] >>= 1; + } + } + l2_table = s->l2_cache + (i * s->l2_size); + goto found; + } + } + /* not found: load a new entry in the least used one */ + min_index = 0; + min_count = 0xffffffff; + for(i = 0; i < L2_CACHE_SIZE; i++) { + if (s->l2_cache_counts[i] < min_count) { + min_count = s->l2_cache_counts[i]; + min_index = i; + } + } + l2_table = s->l2_cache + (min_index * s->l2_size); + lseek(s->fd, (int64_t)l2_offset * 512, SEEK_SET); + if (read(s->fd, l2_table, s->l2_size * sizeof(uint32_t)) != + s->l2_size * sizeof(uint32_t)) + return 0; + s->l2_cache_offsets[min_index] = l2_offset; + s->l2_cache_counts[min_index] = 1; + found: + l2_index = ((offset >> 9) / s->cluster_sectors) % s->l2_size; + cluster_offset = le32_to_cpu(l2_table[l2_index]); + cluster_offset <<= 9; + return cluster_offset; +} + +static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, int *pnum) +{ + BDRVVmdkState *s = bs->opaque; + int index_in_cluster, n; + uint64_t cluster_offset; + + cluster_offset = get_cluster_offset(bs, sector_num << 9); + index_in_cluster = sector_num % s->cluster_sectors; + n = s->cluster_sectors - index_in_cluster; + if (n > nb_sectors) + n = nb_sectors; + *pnum = n; + return (cluster_offset != 0); +} + +static int vmdk_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors) +{ + BDRVVmdkState *s = bs->opaque; + int ret, index_in_cluster, n; + uint64_t cluster_offset; + + while (nb_sectors > 0) { + cluster_offset = get_cluster_offset(bs, sector_num << 9); + index_in_cluster = sector_num % s->cluster_sectors; + n = s->cluster_sectors - index_in_cluster; + if (n > nb_sectors) + n = nb_sectors; + if (!cluster_offset) { + memset(buf, 0, 512 * n); + } else { + lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET); + ret = read(s->fd, buf, n * 512); + if (ret != n * 512) + return -1; + } + nb_sectors -= n; + sector_num += n; + buf += n * 512; + } + return 0; +} + +static int vmdk_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors) +{ + return -1; +} + +static void vmdk_close(BlockDriverState *bs) +{ + BDRVVmdkState *s = bs->opaque; + qemu_free(s->l1_table); + qemu_free(s->l2_cache); + close(s->fd); +} + +BlockDriver bdrv_vmdk = { + "vmdk", + sizeof(BDRVVmdkState), + vmdk_probe, + vmdk_open, + vmdk_read, + vmdk_write, + vmdk_close, + NULL, /* no create yet */ + vmdk_is_allocated, +}; diff --git a/tools/ioemu/block.c b/tools/ioemu/block.c new file mode 100644 index 0000000000..cff0d2a202 --- /dev/null +++ b/tools/ioemu/block.c @@ -0,0 +1,548 @@ +/* + * QEMU System Emulator block driver + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" +#include "block_int.h" + +static BlockDriverState *bdrv_first; +static BlockDriver *first_drv; + +void bdrv_register(BlockDriver *bdrv) +{ + bdrv->next = first_drv; + first_drv = bdrv; +} + +/* create a new block device (by default it is empty) */ +BlockDriverState *bdrv_new(const char *device_name) +{ + BlockDriverState **pbs, *bs; + + bs = qemu_mallocz(sizeof(BlockDriverState)); + if(!bs) + return NULL; + pstrcpy(bs->device_name, sizeof(bs->device_name), device_name); + if (device_name[0] != '\0') { + /* insert at the end */ + pbs = &bdrv_first; + while (*pbs != NULL) + pbs = &(*pbs)->next; + *pbs = bs; + } + return bs; +} + +BlockDriver *bdrv_find_format(const char *format_name) +{ + BlockDriver *drv1; + for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) { + if (!strcmp(drv1->format_name, format_name)) + return drv1; + } + return NULL; +} + +int bdrv_create(BlockDriver *drv, + const char *filename, int64_t size_in_sectors, + const char *backing_file, int flags) +{ + if (!drv->bdrv_create) + return -ENOTSUP; + return drv->bdrv_create(filename, size_in_sectors, backing_file, flags); +} + +static BlockDriver *find_image_format(const char *filename) +{ + int fd, ret, score, score_max; + BlockDriver *drv1, *drv; + uint8_t buf[1024]; + + fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); + if (fd < 0) + return NULL; + ret = read(fd, buf, sizeof(buf)); + if (ret < 0) { + close(fd); + return NULL; + } + close(fd); + + drv = NULL; + score_max = 0; + for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) { + score = drv1->bdrv_probe(buf, ret, filename); + if (score > score_max) { + score_max = score; + drv = drv1; + } + } + return drv; +} + +int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot) +{ + return bdrv_open2(bs, filename, snapshot, NULL); +} + +int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot, + BlockDriver *drv) +{ + int ret; + + bs->read_only = 0; + bs->is_temporary = 0; + bs->encrypted = 0; + + pstrcpy(bs->filename, sizeof(bs->filename), filename); + if (!drv) { + drv = find_image_format(filename); + if (!drv) + return -1; + } + bs->drv = drv; + bs->opaque = qemu_mallocz(drv->instance_size); + if (bs->opaque == NULL && drv->instance_size > 0) + return -1; + + ret = drv->bdrv_open(bs, filename); + if (ret < 0) { + qemu_free(bs->opaque); + return -1; + } +#ifndef _WIN32 + if (bs->is_temporary) { + unlink(filename); + } +#endif + if (bs->backing_file[0] != '\0' && drv->bdrv_is_allocated) { + /* if there is a backing file, use it */ + bs->backing_hd = bdrv_new(""); + if (!bs->backing_hd) { + fail: + bdrv_close(bs); + return -1; + } + if (bdrv_open(bs->backing_hd, bs->backing_file, 0) < 0) + goto fail; + } + + bs->inserted = 1; + + /* call the change callback */ + if (bs->change_cb) + bs->change_cb(bs->change_opaque); + + return 0; +} + +void bdrv_close(BlockDriverState *bs) +{ + if (bs->inserted) { + if (bs->backing_hd) + bdrv_delete(bs->backing_hd); + bs->drv->bdrv_close(bs); + qemu_free(bs->opaque); +#ifdef _WIN32 + if (bs->is_temporary) { + unlink(bs->filename); + } +#endif + bs->opaque = NULL; + bs->drv = NULL; + bs->inserted = 0; + + /* call the change callback */ + if (bs->change_cb) + bs->change_cb(bs->change_opaque); + } +} + +void bdrv_delete(BlockDriverState *bs) +{ + /* XXX: remove the driver list */ + bdrv_close(bs); + qemu_free(bs); +} + +/* commit COW file into the raw image */ +int bdrv_commit(BlockDriverState *bs) +{ + int64_t i; + int n, j; + unsigned char sector[512]; + + if (!bs->inserted) + return -ENOENT; + + if (bs->read_only) { + return -EACCES; + } + + if (!bs->backing_hd) { + return -ENOTSUP; + } + + for (i = 0; i < bs->total_sectors;) { + if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) { + for(j = 0; j < n; j++) { + if (bdrv_read(bs, i, sector, 1) != 0) { + return -EIO; + } + + if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) { + return -EIO; + } + i++; + } + } else { + i += n; + } + } + return 0; +} + +/* return -1 if error */ +int bdrv_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors) +{ + int ret, n; + BlockDriver *drv = bs->drv; + + if (!bs->inserted) + return -1; + + while (nb_sectors > 0) { + if (sector_num == 0 && bs->boot_sector_enabled) { + memcpy(buf, bs->boot_sector_data, 512); + n = 1; + } else if (bs->backing_hd) { + if (drv->bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) { + ret = drv->bdrv_read(bs, sector_num, buf, n); + if (ret < 0) + return -1; + } else { + /* read from the base image */ + ret = bdrv_read(bs->backing_hd, sector_num, buf, n); + if (ret < 0) + return -1; + } + } else { + ret = drv->bdrv_read(bs, sector_num, buf, nb_sectors); + if (ret < 0) + return -1; + /* no need to loop */ + break; + } + nb_sectors -= n; + sector_num += n; + buf += n * 512; + } + return 0; +} + +/* return -1 if error */ +int bdrv_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors) +{ + if (!bs->inserted) + return -1; + if (bs->read_only) + return -1; + return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors); +} + +void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr) +{ + *nb_sectors_ptr = bs->total_sectors; +} + +/* force a given boot sector. */ +void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size) +{ + bs->boot_sector_enabled = 1; + if (size > 512) + size = 512; + memcpy(bs->boot_sector_data, data, size); + memset(bs->boot_sector_data + size, 0, 512 - size); +} + +void bdrv_set_geometry_hint(BlockDriverState *bs, + int cyls, int heads, int secs) +{ + bs->cyls = cyls; + bs->heads = heads; + bs->secs = secs; +} + +void bdrv_set_type_hint(BlockDriverState *bs, int type) +{ + bs->type = type; + bs->removable = ((type == BDRV_TYPE_CDROM || + type == BDRV_TYPE_FLOPPY)); +} + +void bdrv_get_geometry_hint(BlockDriverState *bs, + int *pcyls, int *pheads, int *psecs) +{ + *pcyls = bs->cyls; + *pheads = bs->heads; + *psecs = bs->secs; +} + +int bdrv_get_type_hint(BlockDriverState *bs) +{ + return bs->type; +} + +int bdrv_is_removable(BlockDriverState *bs) +{ + return bs->removable; +} + +int bdrv_is_read_only(BlockDriverState *bs) +{ + return bs->read_only; +} + +int bdrv_is_inserted(BlockDriverState *bs) +{ + return bs->inserted; +} + +int bdrv_is_locked(BlockDriverState *bs) +{ + return bs->locked; +} + +void bdrv_set_locked(BlockDriverState *bs, int locked) +{ + bs->locked = locked; +} + +void bdrv_set_change_cb(BlockDriverState *bs, + void (*change_cb)(void *opaque), void *opaque) +{ + bs->change_cb = change_cb; + bs->change_opaque = opaque; +} + +int bdrv_is_encrypted(BlockDriverState *bs) +{ + if (bs->backing_hd && bs->backing_hd->encrypted) + return 1; + return bs->encrypted; +} + +int bdrv_set_key(BlockDriverState *bs, const char *key) +{ + int ret; + if (bs->backing_hd && bs->backing_hd->encrypted) { + ret = bdrv_set_key(bs->backing_hd, key); + if (ret < 0) + return ret; + if (!bs->encrypted) + return 0; + } + if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key) + return -1; + return bs->drv->bdrv_set_key(bs, key); +} + +void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size) +{ + if (!bs->inserted || !bs->drv) { + buf[0] = '\0'; + } else { + pstrcpy(buf, buf_size, bs->drv->format_name); + } +} + +void bdrv_iterate_format(void (*it)(void *opaque, const char *name), + void *opaque) +{ + BlockDriver *drv; + + for (drv = first_drv; drv != NULL; drv = drv->next) { + it(opaque, drv->format_name); + } +} + +BlockDriverState *bdrv_find(const char *name) +{ + BlockDriverState *bs; + + for (bs = bdrv_first; bs != NULL; bs = bs->next) { + if (!strcmp(name, bs->device_name)) + return bs; + } + return NULL; +} + +void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque) +{ + BlockDriverState *bs; + + for (bs = bdrv_first; bs != NULL; bs = bs->next) { + it(opaque, bs->device_name); + } +} + +const char *bdrv_get_device_name(BlockDriverState *bs) +{ + return bs->device_name; +} + +void bdrv_info(void) +{ + BlockDriverState *bs; + + for (bs = bdrv_first; bs != NULL; bs = bs->next) { + term_printf("%s:", bs->device_name); + term_printf(" type="); + switch(bs->type) { + case BDRV_TYPE_HD: + term_printf("hd"); + break; + case BDRV_TYPE_CDROM: + term_printf("cdrom"); + break; + case BDRV_TYPE_FLOPPY: + term_printf("floppy"); + break; + } + term_printf(" removable=%d", bs->removable); + if (bs->removable) { + term_printf(" locked=%d", bs->locked); + } + if (bs->inserted) { + term_printf(" file=%s", bs->filename); + if (bs->backing_file[0] != '\0') + term_printf(" backing_file=%s", bs->backing_file); + term_printf(" ro=%d", bs->read_only); + term_printf(" drv=%s", bs->drv->format_name); + if (bs->encrypted) + term_printf(" encrypted"); + } else { + term_printf(" [not inserted]"); + } + term_printf("\n"); + } +} + + +/**************************************************************/ +/* RAW block driver */ + +typedef struct BDRVRawState { + int fd; +} BDRVRawState; + +static int raw_probe(const uint8_t *buf, int buf_size, const char *filename) +{ + return 1; /* maybe */ +} + +static int raw_open(BlockDriverState *bs, const char *filename) +{ + BDRVRawState *s = bs->opaque; + int fd; + int64_t size; + + fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE); + if (fd < 0) { + fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE); + if (fd < 0) + return -1; + bs->read_only = 1; + } + size = lseek(fd, 0, SEEK_END); + bs->total_sectors = size / 512; + s->fd = fd; + return 0; +} + +static int raw_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors) +{ + BDRVRawState *s = bs->opaque; + int ret; + + lseek(s->fd, sector_num * 512, SEEK_SET); + ret = read(s->fd, buf, nb_sectors * 512); + if (ret != nb_sectors * 512) + return -1; + return 0; +} + +static int raw_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors) +{ + BDRVRawState *s = bs->opaque; + int ret; + + lseek(s->fd, sector_num * 512, SEEK_SET); + ret = write(s->fd, buf, nb_sectors * 512); + if (ret != nb_sectors * 512) + return -1; + return 0; +} + +static void raw_close(BlockDriverState *bs) +{ + BDRVRawState *s = bs->opaque; + close(s->fd); +} + +static int raw_create(const char *filename, int64_t total_size, + const char *backing_file, int flags) +{ + int fd; + + if (flags || backing_file) + return -ENOTSUP; + + fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, + 0644); + if (fd < 0) + return -EIO; + ftruncate(fd, total_size * 512); + close(fd); + return 0; +} + +BlockDriver bdrv_raw = { + "raw", + sizeof(BDRVRawState), + raw_probe, + raw_open, + raw_read, + raw_write, + raw_close, + raw_create, +}; + +void bdrv_init(void) +{ + bdrv_register(&bdrv_raw); + bdrv_register(&bdrv_cloop); +} diff --git a/tools/ioemu/block_int.h b/tools/ioemu/block_int.h new file mode 100644 index 0000000000..9d047c4ff3 --- /dev/null +++ b/tools/ioemu/block_int.h @@ -0,0 +1,77 @@ +/* + * QEMU System Emulator block driver + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef BLOCK_INT_H +#define BLOCK_INT_H + +struct BlockDriver { + const char *format_name; + int instance_size; + int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename); + int (*bdrv_open)(BlockDriverState *bs, const char *filename); + int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors); + int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors); + void (*bdrv_close)(BlockDriverState *bs); + int (*bdrv_create)(const char *filename, int64_t total_sectors, + const char *backing_file, int flags); + int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num, + int nb_sectors, int *pnum); + int (*bdrv_set_key)(BlockDriverState *bs, const char *key); + struct BlockDriver *next; +}; + +struct BlockDriverState { + int64_t total_sectors; + int read_only; /* if true, the media is read only */ + int inserted; /* if true, the media is present */ + int removable; /* if true, the media can be removed */ + int locked; /* if true, the media cannot temporarily be ejected */ + int encrypted; /* if true, the media is encrypted */ + /* event callback when inserting/removing */ + void (*change_cb)(void *opaque); + void *change_opaque; + + BlockDriver *drv; + void *opaque; + + int boot_sector_enabled; + uint8_t boot_sector_data[512]; + + char filename[1024]; + char backing_file[1024]; /* if non zero, the image is a diff of + this file image */ + int is_temporary; + + BlockDriverState *backing_hd; + + /* NOTE: the following infos are only hints for real hardware + drivers. They are not used by the block driver */ + int cyls, heads, secs; + int type; + char device_name[32]; + BlockDriverState *next; +}; + +#endif /* BLOCK_INT_H */ diff --git a/tools/ioemu/bswap.h b/tools/ioemu/bswap.h new file mode 100644 index 0000000000..37fb04ed97 --- /dev/null +++ b/tools/ioemu/bswap.h @@ -0,0 +1,202 @@ +#ifndef BSWAP_H +#define BSWAP_H + +#include "config-host.h" + +#include + +#ifdef HAVE_BYTESWAP_H +#include +#else + +#define bswap_16(x) \ +({ \ + uint16_t __x = (x); \ + ((uint16_t)( \ + (((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \ + (((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \ +}) + +#define bswap_32(x) \ +({ \ + uint32_t __x = (x); \ + ((uint32_t)( \ + (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ + (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ + (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ + (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \ +}) + +#define bswap_64(x) \ +({ \ + uint64_t __x = (x); \ + ((uint64_t)( \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \ +}) + +#endif /* !HAVE_BYTESWAP_H */ + +static inline uint16_t bswap16(uint16_t x) +{ + return bswap_16(x); +} + +static inline uint32_t bswap32(uint32_t x) +{ + return bswap_32(x); +} + +static inline uint64_t bswap64(uint64_t x) +{ + return bswap_64(x); +} + +static inline void bswap16s(uint16_t *s) +{ + *s = bswap16(*s); +} + +static inline void bswap32s(uint32_t *s) +{ + *s = bswap32(*s); +} + +static inline void bswap64s(uint64_t *s) +{ + *s = bswap64(*s); +} + +#if defined(WORDS_BIGENDIAN) +#define be_bswap(v, size) (v) +#define le_bswap(v, size) bswap ## size(v) +#define be_bswaps(v, size) +#define le_bswaps(p, size) *p = bswap ## size(*p); +#else +#define le_bswap(v, size) (v) +#define be_bswap(v, size) bswap ## size(v) +#define le_bswaps(v, size) +#define be_bswaps(p, size) *p = bswap ## size(*p); +#endif + +#define CPU_CONVERT(endian, size, type)\ +static inline type endian ## size ## _to_cpu(type v)\ +{\ + return endian ## _bswap(v, size);\ +}\ +\ +static inline type cpu_to_ ## endian ## size(type v)\ +{\ + return endian ## _bswap(v, size);\ +}\ +\ +static inline void endian ## size ## _to_cpus(type *p)\ +{\ + endian ## _bswaps(p, size)\ +}\ +\ +static inline void cpu_to_ ## endian ## size ## s(type *p)\ +{\ + endian ## _bswaps(p, size)\ +}\ +\ +static inline type endian ## size ## _to_cpup(const type *p)\ +{\ + return endian ## size ## _to_cpu(*p);\ +}\ +\ +static inline void cpu_to_ ## endian ## size ## w(type *p, type v)\ +{\ + *p = cpu_to_ ## endian ## size(v);\ +} + +CPU_CONVERT(be, 16, uint16_t) +CPU_CONVERT(be, 32, uint32_t) +CPU_CONVERT(be, 64, uint64_t) + +CPU_CONVERT(le, 16, uint16_t) +CPU_CONVERT(le, 32, uint32_t) +CPU_CONVERT(le, 64, uint64_t) + +/* unaligned versions (optimized for frequent unaligned accesses)*/ + +#if defined(__i386__) || defined(__powerpc__) + +#define cpu_to_le16wu(p, v) cpu_to_le16w(p, v) +#define cpu_to_le32wu(p, v) cpu_to_le32w(p, v) +#define le16_to_cpupu(p) le16_to_cpup(p) +#define le32_to_cpupu(p) le32_to_cpup(p) + +#define cpu_to_be16wu(p, v) cpu_to_be16w(p, v) +#define cpu_to_be32wu(p, v) cpu_to_be32w(p, v) + +#else + +static inline void cpu_to_le16wu(uint16_t *p, uint16_t v) +{ + uint8_t *p1 = (uint8_t *)p; + + p1[0] = v; + p1[1] = v >> 8; +} + +static inline void cpu_to_le32wu(uint32_t *p, uint32_t v) +{ + uint8_t *p1 = (uint8_t *)p; + + p1[0] = v; + p1[1] = v >> 8; + p1[2] = v >> 16; + p1[3] = v >> 24; +} + +static inline uint16_t le16_to_cpupu(const uint16_t *p) +{ + const uint8_t *p1 = (const uint8_t *)p; + return p1[0] | (p1[1] << 8); +} + +static inline uint32_t le32_to_cpupu(const uint32_t *p) +{ + const uint8_t *p1 = (const uint8_t *)p; + return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24); +} + +static inline void cpu_to_be16wu(uint16_t *p, uint16_t v) +{ + uint8_t *p1 = (uint8_t *)p; + + p1[0] = v >> 8; + p1[1] = v; +} + +static inline void cpu_to_be32wu(uint32_t *p, uint32_t v) +{ + uint8_t *p1 = (uint8_t *)p; + + p1[0] = v >> 24; + p1[1] = v >> 16; + p1[2] = v >> 8; + p1[3] = v; +} + +#endif + +#ifdef WORDS_BIGENDIAN +#define cpu_to_32wu cpu_to_be32wu +#else +#define cpu_to_32wu cpu_to_le32wu +#endif + +#undef le_bswap +#undef be_bswap +#undef le_bswaps +#undef be_bswaps + +#endif /* BSWAP_H */ diff --git a/tools/ioemu/configure b/tools/ioemu/configure new file mode 100755 index 0000000000..ea9d039aa4 --- /dev/null +++ b/tools/ioemu/configure @@ -0,0 +1,585 @@ +#!/bin/sh +# +# qemu configure script (c) 2003 Fabrice Bellard +# +# set temporary file name +if test ! -z "$TMPDIR" ; then + TMPDIR1="${TMPDIR}" +elif test ! -z "$TEMPDIR" ; then + TMPDIR1="${TEMPDIR}" +else + TMPDIR1="/tmp" +fi + +TMPC="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.c" +TMPO="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.o" +TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}" +TMPS="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.S" + +# default parameters +prefix="" +static="no" +libdir="lib" +cross_prefix="" +cc="gcc" +host_cc="gcc" +ar="ar" +make="make" +strip="strip" +cpu=`uname -m` +target_list="target-i386-dm" +case "$cpu" in + i386|i486|i586|i686|i86pc|BePC) + cpu="i386" + ;; + armv4l) + cpu="armv4l" + ;; + alpha) + cpu="alpha" + ;; + "Power Macintosh"|ppc|ppc64) + cpu="powerpc" + ;; + mips) + cpu="mips" + ;; + s390) + cpu="s390" + ;; + sparc) + cpu="sparc" + ;; + sparc64) + cpu="sparc64" + ;; + ia64) + cpu="ia64" + ;; + m68k) + cpu="m68k" + ;; + x86_64|amd64) + cpu="amd64" + libdir="lib64" + ;; + *) + cpu="unknown" + ;; +esac +gprof="no" +bigendian="no" +mingw32="no" +EXESUF="" +gdbstub="no" +slirp="no" +adlib="no" +oss="no" +fmod="no" +fmod_lib="" +fmod_inc="" + +# OS specific +targetos=`uname -s` +case $targetos in +MINGW32*) +mingw32="yes" +;; +FreeBSD) +bsd="yes" +oss="yes" +;; +NetBSD) +bsd="yes" +oss="yes" +;; +OpenBSD) +bsd="yes" +oss="yes" +;; +Darwin) +bsd="yes" +darwin="yes" +;; +*) +oss="yes" +;; +esac + +if [ "$bsd" = "yes" ] ; then + if [ ! "$darwin" = "yes" ] ; then + make="gmake" + fi + target_list="i386-softmmu ppc-softmmu sparc-softmmu" +fi + +# find source path +# XXX: we assume an absolute path is given when launching configure, +# except in './configure' case. +source_path=${0%configure} +source_path=${source_path%/} +source_path_used="yes" +if test -z "$source_path" -o "$source_path" = "." ; then + source_path=`pwd` + source_path_used="no" +fi + +for opt do + case "$opt" in + --prefix=*) prefix=`echo $opt | cut -d '=' -f 2` + ;; + --interp-prefix=*) interp_prefix=`echo $opt | cut -d '=' -f 2` + ;; + --source-path=*) source_path=`echo $opt | cut -d '=' -f 2` + ;; + --cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2` + ;; + --cc=*) cc=`echo $opt | cut -d '=' -f 2` + ;; + --make=*) make=`echo $opt | cut -d '=' -f 2` + ;; + --extra-cflags=*) CFLAGS="${opt#--extra-cflags=}" + ;; + --extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}" + ;; + --extra-libs=*) extralibs=${opt#--extra-libs=} + ;; + --cpu=*) cpu=`echo $opt | cut -d '=' -f 2` + ;; + --target-list=*) target_list=${opt#--target-list=} + ;; + --enable-gprof) gprof="yes" + ;; + --static) static="yes" + ;; + --disable-sdl) sdl="no" + ;; + --enable-fmod) fmod="yes" + ;; + --fmod-lib=*) fmod_lib=${opt#--fmod-lib=} + ;; + --fmod-inc=*) fmod_inc=${opt#--fmod-inc=} + ;; + --disable-vnc) vnc="no" + ;; + --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-" + ;; + --disable-slirp) slirp="no" + ;; + --enable-adlib) adlib="yes" + ;; + esac +done + +# Checking for CFLAGS +if test -z "$CFLAGS"; then + CFLAGS="-O2" +fi + +cc="${cross_prefix}${cc}" +ar="${cross_prefix}${ar}" +strip="${cross_prefix}${strip}" + +if test "$mingw32" = "yes" ; then + target_list="i386-softmmu ppc-softmmu sparc-softmmu" + EXESUF=".exe" + gdbstub="no" + oss="no" +fi + +if test -z "$cross_prefix" ; then + +# --- +# big/little endian test +cat > $TMPC << EOF +#include +int main(int argc, char ** argv){ + volatile uint32_t i=0x01234567; + return (*((uint8_t*)(&i))) == 0x67; +} +EOF + +if $cc -o $TMPE $TMPC 2>/dev/null ; then +$TMPE && bigendian="yes" +else +echo big/little test failed +fi + +else + +# if cross compiling, cannot launch a program, so make a static guess +if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k"; then + bigendian="yes" +fi + +fi + +# check gcc options support +cat > $TMPC < /dev/null ; then + have_gcc3_options="yes" +fi + +########################################## +# VNC probe + +if test -z "$vnc"; then + +if libvncserver-config --version > /dev/null; then + vnc=yes +else + vnc=no +fi + +fi + +########################################## +# SDL probe + +sdl_too_old=no + +if test -z "$sdl" ; then + +sdl_config="sdl-config" +sdl=no +sdl_static=no + +if test "$mingw32" = "yes" -a ! -z "$cross_prefix" ; then +# win32 cross compilation case + sdl_config="i386-mingw32msvc-sdl-config" + sdl=yes +else +# normal SDL probe +cat > $TMPC << EOF +#include +#undef main /* We don't want SDL to override our main() */ +int main( void ) { return SDL_Init (SDL_INIT_VIDEO); } +EOF + +if $cc -o $TMPE `$sdl_config --cflags 2> /dev/null` $TMPC `$sdl_config --libs 2> /dev/null` 2> /dev/null ; then +_sdlversion=`$sdl_config --version | sed 's/[^0-9]//g'` +if test "$_sdlversion" -lt 121 ; then +sdl_too_old=yes +else +sdl=yes +fi + +# static link with sdl ? +if test "$sdl" = "yes" ; then +aa="no" +`$sdl_config --static-libs | grep \\\-laa > /dev/null` && aa="yes" +sdl_static_libs=`$sdl_config --static-libs` +if [ "$aa" = "yes" ] ; then + sdl_static_libs="$sdl_static_libs `aalib-config --static-libs`" +fi + +if $cc -o $TMPE `$sdl_config --cflags 2> /dev/null` $TMPC $sdl_static_libs 2> /dev/null; then + sdl_static=yes +fi + +fi # static link + +fi # sdl compile test + +fi # cross compilation +fi # -z $sdl + +if test x"$1" = x"-h" -o x"$1" = x"--help" ; then +cat << EOF + +Usage: configure [options] +Options: [defaults in brackets after descriptions] + +EOF +echo "Standard options:" +echo " --help print this message" +echo " --prefix=PREFIX install in PREFIX [$prefix]" +echo " --interp-prefix=PREFIX where to find shared libraries, etc." +echo " use %M for cpu name [$interp_prefix]" +echo " --target-list=LIST set target list [$target_list]" +echo " --disable-vnc disable vnc support (else configure checks" +echo " for libvncserver-config in your PATH)" +echo "" +echo "Advanced options (experts only):" +echo " --source-path=PATH path of source code [$source_path]" +echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]" +echo " --cc=CC use C compiler CC [$cc]" +echo " --make=MAKE use specified make [$make]" +echo " --static enable static build [$static]" +echo " --enable-mingw32 enable Win32 cross compilation with mingw32" +echo " --enable-fmod enable FMOD audio output driver" +echo " --fmod-lib path to FMOD library" +echo " --fmod-inc path to FMOD includes" +echo "" +echo "NOTE: The object files are build at the place where configure is launched" +exit 1 +fi + +#installroot=$source_path/../../dist/install +installroot= + +if test "$mingw32" = "yes" ; then +if test -z "$prefix" ; then + prefix="/c/Program Files/Qemu" +fi + +mandir="$prefix" +datadir="$prefix" +docdir="$prefix" +bindir="$prefix" +configdir="" +else +if test -z "$prefix" ; then + prefix="usr/local" +fi +mandir="$installroot/$prefix/share/man" +datadir="$installroot/$prefix/share/qemu" +docdir="$installroot/$prefix/share/doc/qemu" +bindir="$installroot/$prefix/bin" +configdir="$installroot/etc/xen" +fi + +echo "Install prefix $prefix" +echo "BIOS directory $datadir" +echo "binary directory $bindir" +if test "$mingw32" = "no" ; then +echo "Manual directory $mandir" +fi +echo "Source path $source_path" +echo "C compiler $cc" +echo "make $make" +echo "host CPU $cpu" +echo "host big endian $bigendian" +echo "target list $target_list" +echo "gprof enabled $gprof" +echo "static build $static" +echo "VNC support $vnc" +echo "SDL support $sdl" +echo "SDL static link $sdl_static" +echo "mingw32 support $mingw32" +echo "Adlib support $adlib" +echo -n "FMOD support $fmod" +if test $fmod = "yes"; then + echo -n " (lib='$fmod_lib' include='$fmod_inc')" +fi +echo "" + +if test $sdl_too_old = "yes"; then +echo "-> Your SDL version is too old - please upgrade to have FFplay/SDL support" +fi +if test "$sdl_static" = "no"; then + echo "WARNING: cannot compile statically with SDL - qemu-fast won't have a graphical output" +fi + +config_mak="config-host.mak" +config_h="config-host.h" + +#echo "Creating $config_mak and $config_h" + +echo "# Automatically generated by configure - do not modify" > $config_mak +echo "/* Automatically generated by configure - do not modify */" > $config_h + +echo "prefix=$prefix" >> $config_mak +echo "bindir=$bindir" >> $config_mak +echo "mandir=$mandir" >> $config_mak +echo "datadir=$datadir" >> $config_mak +echo "docdir=$docdir" >> $config_mak +echo "configdir=$configdir" >> $config_mak +echo "LIBDIR=$libdir" >> $config_mak +echo "#define CONFIG_QEMU_SHAREDIR \"$datadir\"" >> $config_h +echo "MAKE=$make" >> $config_mak +echo "CC=$cc" >> $config_mak +if test "$have_gcc3_options" = "yes" ; then + echo "HAVE_GCC3_OPTIONS=yes" >> $config_mak +fi +echo "HOST_CC=$host_cc" >> $config_mak +echo "AR=$ar" >> $config_mak +echo "STRIP=$strip -s -R .comment -R .note" >> $config_mak +echo "CFLAGS=$CFLAGS" >> $config_mak +echo "LDFLAGS=$LDFLAGS" >> $config_mak +echo "EXESUF=$EXESUF" >> $config_mak + +if test "$bigendian" = "yes" ; then + echo "WORDS_BIGENDIAN=yes" >> $config_mak + echo "#define WORDS_BIGENDIAN 1" >> $config_h +fi +if test "$mingw32" = "yes" ; then + echo "CONFIG_WIN32=yes" >> $config_mak + echo "#define CONFIG_WIN32 1" >> $config_h +elif test -f "/usr/include/byteswap.h" ; then + echo "#define HAVE_BYTESWAP_H 1" >> $config_h +fi +if test "$darwin" = "yes" ; then + echo "CONFIG_DARWIN=yes" >> $config_mak + echo "#define CONFIG_DARWIN 1" >> $config_h +fi +if test "$gdbstub" = "yes" ; then + echo "CONFIG_GDBSTUB=yes" >> $config_mak + echo "#define CONFIG_GDBSTUB 1" >> $config_h +fi +if test "$gprof" = "yes" ; then + echo "TARGET_GPROF=yes" >> $config_mak + echo "#define HAVE_GPROF 1" >> $config_h +fi +if test "$static" = "yes" ; then + echo "CONFIG_STATIC=yes" >> $config_mak + echo "#define CONFIG_STATIC 1" >> $config_h +fi +if test "$slirp" = "yes" ; then + echo "CONFIG_SLIRP=yes" >> $config_mak + echo "#define CONFIG_SLIRP 1" >> $config_h +fi +if test "$adlib" = "yes" ; then + echo "CONFIG_ADLIB=yes" >> $config_mak + echo "#define CONFIG_ADLIB 1" >> $config_h +fi +if test "$oss" = "yes" ; then + echo "CONFIG_OSS=yes" >> $config_mak + echo "#define CONFIG_OSS 1" >> $config_h +fi +if test "$fmod" = "yes" ; then + echo "CONFIG_FMOD=yes" >> $config_mak + echo "CONFIG_FMOD_LIB=$fmod_lib" >> $config_mak + echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak + echo "#define CONFIG_FMOD 1" >> $config_h +fi +echo -n "VERSION=" >>$config_mak +head $source_path/VERSION >>$config_mak +echo "" >>$config_mak +echo -n "#define QEMU_VERSION \"" >> $config_h +head $source_path/VERSION >> $config_h +echo "\"" >> $config_h + +echo "SRC_PATH=$source_path" >> $config_mak +echo "TARGET_DIRS=$target_list" >> $config_mak + +# XXX: suppress that +if [ "$bsd" = "yes" ] ; then + echo "#define O_LARGEFILE 0" >> $config_h + echo "#define MAP_ANONYMOUS MAP_ANON" >> $config_h + echo "#define _BSD 1" >> $config_h +fi + +if test "$vnc" = "yes"; then + echo "CONFIG_VNC=yes" >> $config_mak + vnc_cflags=`libvncserver-config --cflags` + if [ -z $vnc_cflags ]; then + vnc_cflags="/usr/include" + fi + echo "VNC_CFLAGS=$vnc_cflags" >> $config_mak +fi + +if test "$sdl" = "yes"; then + echo "CONFIG_SDL=yes" >> $config_mak + echo "SDL_CFLAGS=`$sdl_config --cflags`" >> $config_mak +fi + +for target in $target_list; do + +target_dir="$target" +config_mak=$target_dir/config.mak +config_h=$target_dir/config.h +target_cpu=`echo $target | cut -d '-' -f 2` +[ "$target_cpu" = "ppc" ] && target_bigendian=yes +target_softmmu="no" +if expr $target : '.*-softmmu' > /dev/null ; then + target_softmmu="yes" +fi +target_user_only="no" +if expr $target : '.*-user' > /dev/null ; then + target_user_only="yes" +fi +#echo "Creating $config_mak, $config_h and $target_dir/Makefile" + +mkdir -p $target_dir +if test "$target" = "arm-user" ; then + mkdir -p $target_dir/nwfpe +fi +if test "$target_user_only" = "no" ; then + mkdir -p $target_dir/slirp +fi + +ln -sf $source_path/Makefile.target $target_dir/Makefile + +echo "# Automatically generated by configure - do not modify" > $config_mak +echo "/* Automatically generated by configure - do not modify */" > $config_h + + +echo "include ../config-host.mak" >> $config_mak +echo "#include \"../config-host.h\"" >> $config_h + +if test "$target_cpu" = "i386" ; then + echo "TARGET_ARCH=i386" >> $config_mak + echo "#define TARGET_ARCH \"i386\"" >> $config_h + echo "#define TARGET_I386 1" >> $config_h +fi + +interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"` +echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h + +if test "$target_bigendian" = "yes" ; then + echo "TARGET_WORDS_BIGENDIAN=yes" >> $config_mak + echo "#define TARGET_WORDS_BIGENDIAN 1" >> $config_h +fi +if test "$target_softmmu" = "yes" ; then + echo "CONFIG_SOFTMMU=yes" >> $config_mak + echo "#define CONFIG_SOFTMMU 1" >> $config_h +fi +if test "$target_user_only" = "yes" ; then + echo "CONFIG_USER_ONLY=yes" >> $config_mak + echo "#define CONFIG_USER_ONLY 1" >> $config_h +fi + +if test "$target_user_only" = "no"; then + if test "$vnc" = "yes"; then + echo "#define CONFIG_VNC 1" >> $config_h + echo "CONFIG_VNC=yes" >> $config_mak + echo "VNC_CFLAGS=`libvncserver-config --cflags`" >> $config_mak + echo "VNC_LIBS=`libvncserver-config --libs`" >> $config_mak + fi +fi + +# sdl defines + +if test "$sdl" = "yes" -a "$target_user_only" = "no"; then + if test "$target_softmmu" = "no" -o "$static" = "yes"; then + sdl1=$sdl_static + else + sdl1=$sdl + fi + if test "$sdl1" = "yes" ; then + echo "#define CONFIG_SDL 1" >> $config_h + echo "CONFIG_SDL=yes" >> $config_mak + if test "$target_softmmu" = "no" -o "$static" = "yes"; then + echo "SDL_LIBS=$sdl_static_libs" >> $config_mak + else + echo "SDL_LIBS=`$sdl_config --libs`" >> $config_mak + fi + echo -n "SDL_CFLAGS=`$sdl_config --cflags`" >> $config_mak + if [ "${aa}" = "yes" ] ; then + echo -n " `aalib-config --cflags`" >> $config_mak ; + fi + echo "" >> $config_mak + fi +fi + +done # for target in $targets + +# build tree in object directory if source path is different from current one +if test "$source_path_used" = "yes" ; then + DIRS="tests" + FILES="Makefile tests/Makefile" + for dir in $DIRS ; do + mkdir -p $dir + done + for f in $FILES ; do + ln -sf $source_path/$f $f + done +fi + +rm -f $TMPO $TMPC $TMPE $TMPS diff --git a/tools/ioemu/console.c b/tools/ioemu/console.c new file mode 100644 index 0000000000..d7588016db --- /dev/null +++ b/tools/ioemu/console.c @@ -0,0 +1,731 @@ +/* + * QEMU graphical console + * + * Copyright (c) 2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +#define DEFAULT_BACKSCROLL 512 +#define MAX_CONSOLES 12 + +#define RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) +#define RGB(r, g, b) RGBA(r, g, b, 0xff) + +typedef struct TextCell { + uint8_t ch; + uint8_t bgcol:4; + uint8_t fgcol:4; +} TextCell; + +#define MAX_ESC_PARAMS 3 + +enum TTYState { + TTY_STATE_NORM, + TTY_STATE_ESC, + TTY_STATE_CSI, +}; + +struct TextConsole { + int text_console; /* true if text console */ + DisplayState *ds; + int g_width, g_height; + int width; + int height; + int total_height; + int backscroll_height; + int fgcol; + int bgcol; + int x, y; + int y_displayed; + int y_base; + TextCell *cells; + + enum TTYState state; + int esc_params[MAX_ESC_PARAMS]; + int nb_esc_params; + + /* kbd read handler */ + IOReadHandler *fd_read; + void *fd_opaque; +}; + +static TextConsole *active_console; +static TextConsole *consoles[MAX_CONSOLES]; +static int nb_consoles = 0; + +/* convert a RGBA color to a color index usable in graphic primitives */ +static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba) +{ + unsigned int r, g, b, color; + + switch(ds->depth) { +#if 0 + case 8: + r = (rgba >> 16) & 0xff; + g = (rgba >> 8) & 0xff; + b = (rgba) & 0xff; + color = (rgb_to_index[r] * 6 * 6) + + (rgb_to_index[g] * 6) + + (rgb_to_index[b]); + break; +#endif + case 15: + r = (rgba >> 16) & 0xff; + g = (rgba >> 8) & 0xff; + b = (rgba) & 0xff; + color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3); + break; + case 16: + r = (rgba >> 16) & 0xff; + g = (rgba >> 8) & 0xff; + b = (rgba) & 0xff; + color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); + break; + case 32: + default: + color = rgba; + break; + } + return color; +} + +static void vga_fill_rect (DisplayState *ds, + int posx, int posy, int width, int height, uint32_t color) +{ + uint8_t *d, *d1; + int x, y, bpp; + + bpp = (ds->depth + 7) >> 3; + d1 = ds->data + + ds->linesize * posy + bpp * posx; + for (y = 0; y < height; y++) { + d = d1; + switch(bpp) { + case 1: + for (x = 0; x < width; x++) { + *((uint8_t *)d) = color; + d++; + } + break; + case 2: + for (x = 0; x < width; x++) { + *((uint16_t *)d) = color; + d += 2; + } + break; + case 4: + for (x = 0; x < width; x++) { + *((uint32_t *)d) = color; + d += 4; + } + break; + } + d1 += ds->linesize; + } +} + +/* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */ +static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w, int h) +{ + const uint8_t *s; + uint8_t *d; + int wb, y, bpp; + + bpp = (ds->depth + 7) >> 3; + wb = w * bpp; + if (yd <= ys) { + s = ds->data + + ds->linesize * ys + bpp * xs; + d = ds->data + + ds->linesize * yd + bpp * xd; + for (y = 0; y < h; y++) { + memmove(d, s, wb); + d += ds->linesize; + s += ds->linesize; + } + } else { + s = ds->data + + ds->linesize * (ys + h - 1) + bpp * xs; + d = ds->data + + ds->linesize * (yd + h - 1) + bpp * xd; + for (y = 0; y < h; y++) { + memmove(d, s, wb); + d -= ds->linesize; + s -= ds->linesize; + } + } +} + +/***********************************************************/ +/* basic char display */ + +#define FONT_HEIGHT 16 +#define FONT_WIDTH 8 + +#include "vgafont.h" + +#define cbswap_32(__x) \ +((uint32_t)( \ + (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ + (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ + (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ + (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )) + +#ifdef WORDS_BIGENDIAN +#define PAT(x) x +#else +#define PAT(x) cbswap_32(x) +#endif + +static const uint32_t dmask16[16] = { + PAT(0x00000000), + PAT(0x000000ff), + PAT(0x0000ff00), + PAT(0x0000ffff), + PAT(0x00ff0000), + PAT(0x00ff00ff), + PAT(0x00ffff00), + PAT(0x00ffffff), + PAT(0xff000000), + PAT(0xff0000ff), + PAT(0xff00ff00), + PAT(0xff00ffff), + PAT(0xffff0000), + PAT(0xffff00ff), + PAT(0xffffff00), + PAT(0xffffffff), +}; + +static const uint32_t dmask4[4] = { + PAT(0x00000000), + PAT(0x0000ffff), + PAT(0xffff0000), + PAT(0xffffffff), +}; + +static uint32_t color_table[8]; + +static const uint32_t color_table_rgb[8] = { + RGB(0x00, 0x00, 0x00), + RGB(0xff, 0x00, 0x00), + RGB(0x00, 0xff, 0x00), + RGB(0xff, 0xff, 0x00), + RGB(0x00, 0x00, 0xff), + RGB(0xff, 0x00, 0xff), + RGB(0x00, 0xff, 0xff), + RGB(0xff, 0xff, 0xff), +}; + +static inline unsigned int col_expand(DisplayState *ds, unsigned int col) +{ + switch(ds->depth) { + case 8: + col |= col << 8; + col |= col << 16; + break; + case 15: + case 16: + col |= col << 16; + break; + default: + break; + } + + return col; +} + +static void vga_putcharxy(DisplayState *ds, int x, int y, int ch, + unsigned int fgcol, unsigned int bgcol) +{ + uint8_t *d; + const uint8_t *font_ptr; + unsigned int font_data, linesize, xorcol, bpp; + int i; + + bpp = (ds->depth + 7) >> 3; + d = ds->data + + ds->linesize * y * FONT_HEIGHT + bpp * x * FONT_WIDTH; + linesize = ds->linesize; + font_ptr = vgafont16 + FONT_HEIGHT * ch; + xorcol = bgcol ^ fgcol; + switch(ds->depth) { + case 8: + for(i = 0; i < FONT_HEIGHT; i++) { + font_data = *font_ptr++; + ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; + d += linesize; + } + break; + case 16: + case 15: + for(i = 0; i < FONT_HEIGHT; i++) { + font_data = *font_ptr++; + ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol; + ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol; + ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol; + d += linesize; + } + break; + case 32: + for(i = 0; i < FONT_HEIGHT; i++) { + font_data = *font_ptr++; + ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol; + d += linesize; + } + break; + } +} + +static void text_console_resize(TextConsole *s) +{ + TextCell *cells, *c, *c1; + int w1, x, y, last_width; + + last_width = s->width; + s->width = s->g_width / FONT_WIDTH; + s->height = s->g_height / FONT_HEIGHT; + + w1 = last_width; + if (s->width < w1) + w1 = s->width; + + cells = qemu_malloc(s->width * s->total_height * sizeof(TextCell)); + for(y = 0; y < s->total_height; y++) { + c = &cells[y * s->width]; + if (w1 > 0) { + c1 = &s->cells[y * last_width]; + for(x = 0; x < w1; x++) { + *c++ = *c1++; + } + } + for(x = w1; x < s->width; x++) { + c->ch = ' '; + c->fgcol = 7; + c->bgcol = 0; + c++; + } + } + qemu_free(s->cells); + s->cells = cells; +} + +static void update_xy(TextConsole *s, int x, int y) +{ + TextCell *c; + int y1, y2; + + if (s == active_console) { + y1 = (s->y_base + y) % s->total_height; + y2 = y1 - s->y_displayed; + if (y2 < 0) + y2 += s->total_height; + if (y2 < s->height) { + c = &s->cells[y1 * s->width + x]; + vga_putcharxy(s->ds, x, y2, c->ch, + color_table[c->fgcol], color_table[c->bgcol]); + dpy_update(s->ds, x * FONT_WIDTH, y2 * FONT_HEIGHT, + FONT_WIDTH, FONT_HEIGHT); + } + } +} + +static void console_show_cursor(TextConsole *s, int show) +{ + TextCell *c; + int y, y1; + + if (s == active_console) { + y1 = (s->y_base + s->y) % s->total_height; + y = y1 - s->y_displayed; + if (y < 0) + y += s->total_height; + if (y < s->height) { + c = &s->cells[y1 * s->width + s->x]; + if (show) { + vga_putcharxy(s->ds, s->x, y, c->ch, + color_table[0], color_table[7]); + } else { + vga_putcharxy(s->ds, s->x, y, c->ch, + color_table[c->fgcol], color_table[c->bgcol]); + } + dpy_update(s->ds, s->x * FONT_WIDTH, y * FONT_HEIGHT, + FONT_WIDTH, FONT_HEIGHT); + } + } +} + +static void console_refresh(TextConsole *s) +{ + TextCell *c; + int x, y, y1; + + if (s != active_console) + return; + + vga_fill_rect(s->ds, 0, 0, s->ds->width, s->ds->height, + color_table[0]); + y1 = s->y_displayed; + for(y = 0; y < s->height; y++) { + c = s->cells + y1 * s->width; + for(x = 0; x < s->width; x++) { + vga_putcharxy(s->ds, x, y, c->ch, + color_table[c->fgcol], color_table[c->bgcol]); + c++; + } + if (++y1 == s->total_height) + y1 = 0; + } + dpy_update(s->ds, 0, 0, s->ds->width, s->ds->height); + console_show_cursor(s, 1); +} + +static void console_scroll(int ydelta) +{ + TextConsole *s; + int i, y1; + + s = active_console; + if (!s || !s->text_console) + return; + + if (ydelta > 0) { + for(i = 0; i < ydelta; i++) { + if (s->y_displayed == s->y_base) + break; + if (++s->y_displayed == s->total_height) + s->y_displayed = 0; + } + } else { + ydelta = -ydelta; + i = s->backscroll_height; + if (i > s->total_height - s->height) + i = s->total_height - s->height; + y1 = s->y_base - i; + if (y1 < 0) + y1 += s->total_height; + for(i = 0; i < ydelta; i++) { + if (s->y_displayed == y1) + break; + if (--s->y_displayed < 0) + s->y_displayed = s->total_height - 1; + } + } + console_refresh(s); +} + +static void console_put_lf(TextConsole *s) +{ + TextCell *c; + int x, y1; + + s->x = 0; + s->y++; + if (s->y >= s->height) { + s->y = s->height - 1; + + if (s->y_displayed == s->y_base) { + if (++s->y_displayed == s->total_height) + s->y_displayed = 0; + } + if (++s->y_base == s->total_height) + s->y_base = 0; + if (s->backscroll_height < s->total_height) + s->backscroll_height++; + y1 = (s->y_base + s->height - 1) % s->total_height; + c = &s->cells[y1 * s->width]; + for(x = 0; x < s->width; x++) { + c->ch = ' '; + c->fgcol = s->fgcol; + c->bgcol = s->bgcol; + c++; + } + if (s == active_console && s->y_displayed == s->y_base) { + vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0, + s->width * FONT_WIDTH, + (s->height - 1) * FONT_HEIGHT); + vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT, + s->width * FONT_WIDTH, FONT_HEIGHT, + color_table[s->bgcol]); + dpy_update(s->ds, 0, 0, + s->width * FONT_WIDTH, s->height * FONT_HEIGHT); + } + } +} + +static void console_putchar(TextConsole *s, int ch) +{ + TextCell *c; + int y1, i, x; + + switch(s->state) { + case TTY_STATE_NORM: + switch(ch) { + case '\r': + s->x = 0; + break; + case '\n': + console_put_lf(s); + break; + case 27: + s->state = TTY_STATE_ESC; + break; + default: + y1 = (s->y_base + s->y) % s->total_height; + c = &s->cells[y1 * s->width + s->x]; + c->ch = ch; + c->fgcol = s->fgcol; + c->bgcol = s->bgcol; + update_xy(s, s->x, s->y); + s->x++; + if (s->x >= s->width) + console_put_lf(s); + break; + } + break; + case TTY_STATE_ESC: + if (ch == '[') { + for(i=0;iesc_params[i] = 0; + s->nb_esc_params = 0; + s->state = TTY_STATE_CSI; + } else { + s->state = TTY_STATE_NORM; + } + break; + case TTY_STATE_CSI: + if (ch >= '0' && ch <= '9') { + if (s->nb_esc_params < MAX_ESC_PARAMS) { + s->esc_params[s->nb_esc_params] = + s->esc_params[s->nb_esc_params] * 10 + ch - '0'; + } + } else { + s->nb_esc_params++; + if (ch == ';') + break; + s->state = TTY_STATE_NORM; + switch(ch) { + case 'D': + if (s->x > 0) + s->x--; + break; + case 'C': + if (s->x < (s->width - 1)) + s->x++; + break; + case 'K': + /* clear to eol */ + y1 = (s->y_base + s->y) % s->total_height; + for(x = s->x; x < s->width; x++) { + c = &s->cells[y1 * s->width + x]; + c->ch = ' '; + c->fgcol = s->fgcol; + c->bgcol = s->bgcol; + c++; + update_xy(s, x, s->y); + } + break; + default: + break; + } + break; + } + } +} + +void console_select(unsigned int index) +{ + TextConsole *s; + + if (index >= MAX_CONSOLES) + return; + s = consoles[index]; + if (s) { + active_console = s; + if (s->text_console) { + if (s->g_width != s->ds->width || + s->g_height != s->ds->height) { + s->g_width = s->ds->width; + s->g_height = s->ds->height; + text_console_resize(s); + } + console_refresh(s); + } + } +} + +static int console_puts(CharDriverState *chr, const uint8_t *buf, int len) +{ + TextConsole *s = chr->opaque; + int i; + + console_show_cursor(s, 0); + for(i = 0; i < len; i++) { + console_putchar(s, buf[i]); + } + console_show_cursor(s, 1); + return len; +} + +static void console_chr_add_read_handler(CharDriverState *chr, + IOCanRWHandler *fd_can_read, + IOReadHandler *fd_read, void *opaque) +{ + TextConsole *s = chr->opaque; + s->fd_read = fd_read; + s->fd_opaque = opaque; +} + +static void console_send_event(CharDriverState *chr, int event) +{ + TextConsole *s = chr->opaque; + int i; + + if (event == CHR_EVENT_FOCUS) { + for(i = 0; i < nb_consoles; i++) { + if (consoles[i] == s) { + console_select(i); + break; + } + } + } +} + +/* called when an ascii key is pressed */ +void kbd_put_keysym(int keysym) +{ + TextConsole *s; + uint8_t buf[16], *q; + int c; + + s = active_console; + if (!s || !s->text_console) + return; + + switch(keysym) { + case QEMU_KEY_CTRL_UP: + console_scroll(-1); + break; + case QEMU_KEY_CTRL_DOWN: + console_scroll(1); + break; + case QEMU_KEY_CTRL_PAGEUP: + console_scroll(-10); + break; + case QEMU_KEY_CTRL_PAGEDOWN: + console_scroll(10); + break; + default: + if (s->fd_read) { + /* convert the QEMU keysym to VT100 key string */ + q = buf; + if (keysym >= 0xe100 && keysym <= 0xe11f) { + *q++ = '\033'; + *q++ = '['; + c = keysym - 0xe100; + if (c >= 10) + *q++ = '0' + (c / 10); + *q++ = '0' + (c % 10); + *q++ = '~'; + } else if (keysym >= 0xe120 && keysym <= 0xe17f) { + *q++ = '\033'; + *q++ = '['; + *q++ = keysym & 0xff; + } else { + *q++ = keysym; + } + s->fd_read(s->fd_opaque, buf, q - buf); + } + break; + } +} + +TextConsole *graphic_console_init(DisplayState *ds) +{ + TextConsole *s; + + if (nb_consoles >= MAX_CONSOLES) + return NULL; + s = qemu_mallocz(sizeof(TextConsole)); + if (!s) { + return NULL; + } + if (!active_console) + active_console = s; + s->ds = ds; + consoles[nb_consoles++] = s; + return s; +} + +int is_active_console(TextConsole *s) +{ + return s == active_console; +} + +CharDriverState *text_console_init(DisplayState *ds) +{ + CharDriverState *chr; + TextConsole *s; + int i; + static int color_inited; + + chr = qemu_mallocz(sizeof(CharDriverState)); + if (!chr) + return NULL; + s = graphic_console_init(ds); + if (!s) { + free(chr); + return NULL; + } + s->text_console = 1; + chr->opaque = s; + chr->chr_write = console_puts; + chr->chr_add_read_handler = console_chr_add_read_handler; + chr->chr_send_event = console_send_event; + + if (!color_inited) { + color_inited = 1; + for(i = 0; i < 8; i++) { + color_table[i] = col_expand(s->ds, + vga_get_color(s->ds, color_table_rgb[i])); + } + } + s->y_displayed = 0; + s->y_base = 0; + s->total_height = DEFAULT_BACKSCROLL; + s->x = 0; + s->y = 0; + s->fgcol = 7; + s->bgcol = 0; + s->g_width = s->ds->width; + s->g_height = s->ds->height; + text_console_resize(s); + + return chr; +} diff --git a/tools/ioemu/cpu-all.h b/tools/ioemu/cpu-all.h new file mode 100644 index 0000000000..6e9a8b8ac5 --- /dev/null +++ b/tools/ioemu/cpu-all.h @@ -0,0 +1,688 @@ +/* + * defines common to all virtual CPUs + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef CPU_ALL_H +#define CPU_ALL_H + +#if defined(__arm__) || defined(__sparc__) +#define WORDS_ALIGNED +#endif + +/* some important defines: + * + * WORDS_ALIGNED : if defined, the host cpu can only make word aligned + * memory accesses. + * + * WORDS_BIGENDIAN : if defined, the host cpu is big endian and + * otherwise little endian. + * + * (TARGET_WORDS_ALIGNED : same for target cpu (not supported yet)) + * + * TARGET_WORDS_BIGENDIAN : same for target cpu + */ + +#include "bswap.h" + +#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) +#define BSWAP_NEEDED +#endif + +#ifdef BSWAP_NEEDED + +static inline uint16_t tswap16(uint16_t s) +{ + return bswap16(s); +} + +static inline uint32_t tswap32(uint32_t s) +{ + return bswap32(s); +} + +static inline uint64_t tswap64(uint64_t s) +{ + return bswap64(s); +} + +static inline void tswap16s(uint16_t *s) +{ + *s = bswap16(*s); +} + +static inline void tswap32s(uint32_t *s) +{ + *s = bswap32(*s); +} + +static inline void tswap64s(uint64_t *s) +{ + *s = bswap64(*s); +} + +#else + +static inline uint16_t tswap16(uint16_t s) +{ + return s; +} + +static inline uint32_t tswap32(uint32_t s) +{ + return s; +} + +static inline uint64_t tswap64(uint64_t s) +{ + return s; +} + +static inline void tswap16s(uint16_t *s) +{ +} + +static inline void tswap32s(uint32_t *s) +{ +} + +static inline void tswap64s(uint64_t *s) +{ +} + +#endif + +#if TARGET_LONG_SIZE == 4 +#define tswapl(s) tswap32(s) +#define tswapls(s) tswap32s((uint32_t *)(s)) +#else +#define tswapl(s) tswap64(s) +#define tswapls(s) tswap64s((uint64_t *)(s)) +#endif + +/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */ +typedef union { + double d; +#if !defined(WORDS_BIGENDIAN) && !defined(__arm__) + struct { + uint32_t lower; + uint32_t upper; + } l; +#else + struct { + uint32_t upper; + uint32_t lower; + } l; +#endif + uint64_t ll; +} CPU_DoubleU; + +/* CPU memory access without any memory or io remapping */ + +/* + * the generic syntax for the memory accesses is: + * + * load: ld{type}{sign}{size}{endian}_{access_type}(ptr) + * + * store: st{type}{size}{endian}_{access_type}(ptr, val) + * + * type is: + * (empty): integer access + * f : float access + * + * sign is: + * (empty): for floats or 32 bit size + * u : unsigned + * s : signed + * + * size is: + * b: 8 bits + * w: 16 bits + * l: 32 bits + * q: 64 bits + * + * endian is: + * (empty): target cpu endianness or 8 bit access + * r : reversed target cpu endianness (not implemented yet) + * be : big endian (not implemented yet) + * le : little endian (not implemented yet) + * + * access_type is: + * raw : host memory access + * user : user mode access using soft MMU + * kernel : kernel mode access using soft MMU + */ +static inline int ldub_raw(void *ptr) +{ + return *(uint8_t *)ptr; +} + +static inline int ldsb_raw(void *ptr) +{ + return *(int8_t *)ptr; +} + +static inline void stb_raw(void *ptr, int v) +{ + *(uint8_t *)ptr = v; +} + +/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the + kernel handles unaligned load/stores may give better results, but + it is a system wide setting : bad */ +#if !defined(TARGET_WORDS_BIGENDIAN) && (defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)) + +/* conservative code for little endian unaligned accesses */ +static inline int lduw_raw(void *ptr) +{ +#ifdef __powerpc__ + int val; + __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr)); + return val; +#else + uint8_t *p = ptr; + return p[0] | (p[1] << 8); +#endif +} + +static inline int ldsw_raw(void *ptr) +{ +#ifdef __powerpc__ + int val; + __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr)); + return (int16_t)val; +#else + uint8_t *p = ptr; + return (int16_t)(p[0] | (p[1] << 8)); +#endif +} + +static inline int ldl_raw(void *ptr) +{ +#ifdef __powerpc__ + int val; + __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr)); + return val; +#else + uint8_t *p = ptr; + return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); +#endif +} + +static inline uint64_t ldq_raw(void *ptr) +{ + uint8_t *p = ptr; + uint32_t v1, v2; + v1 = ldl_raw(p); + v2 = ldl_raw(p + 4); + return v1 | ((uint64_t)v2 << 32); +} + +static inline void stw_raw(void *ptr, int v) +{ +#ifdef __powerpc__ + __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr)); +#else + uint8_t *p = ptr; + p[0] = v; + p[1] = v >> 8; +#endif +} + +static inline void stl_raw(void *ptr, int v) +{ +#ifdef __powerpc__ + __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr)); +#else + uint8_t *p = ptr; + p[0] = v; + p[1] = v >> 8; + p[2] = v >> 16; + p[3] = v >> 24; +#endif +} + +static inline void stq_raw(void *ptr, uint64_t v) +{ + uint8_t *p = ptr; + stl_raw(p, (uint32_t)v); + stl_raw(p + 4, v >> 32); +} + +/* float access */ + +static inline float ldfl_raw(void *ptr) +{ + union { + float f; + uint32_t i; + } u; + u.i = ldl_raw(ptr); + return u.f; +} + +static inline void stfl_raw(void *ptr, float v) +{ + union { + float f; + uint32_t i; + } u; + u.f = v; + stl_raw(ptr, u.i); +} + +static inline double ldfq_raw(void *ptr) +{ + CPU_DoubleU u; + u.l.lower = ldl_raw(ptr); + u.l.upper = ldl_raw(ptr + 4); + return u.d; +} + +static inline void stfq_raw(void *ptr, double v) +{ + CPU_DoubleU u; + u.d = v; + stl_raw(ptr, u.l.lower); + stl_raw(ptr + 4, u.l.upper); +} + +#elif defined(TARGET_WORDS_BIGENDIAN) && (!defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)) + +static inline int lduw_raw(void *ptr) +{ +#if defined(__i386__) + int val; + asm volatile ("movzwl %1, %0\n" + "xchgb %b0, %h0\n" + : "=q" (val) + : "m" (*(uint16_t *)ptr)); + return val; +#else + uint8_t *b = (uint8_t *) ptr; + return ((b[0] << 8) | b[1]); +#endif +} + +static inline int ldsw_raw(void *ptr) +{ +#if defined(__i386__) + int val; + asm volatile ("movzwl %1, %0\n" + "xchgb %b0, %h0\n" + : "=q" (val) + : "m" (*(uint16_t *)ptr)); + return (int16_t)val; +#else + uint8_t *b = (uint8_t *) ptr; + return (int16_t)((b[0] << 8) | b[1]); +#endif +} + +static inline int ldl_raw(void *ptr) +{ +#if defined(__i386__) || defined(__x86_64__) + int val; + asm volatile ("movl %1, %0\n" + "bswap %0\n" + : "=r" (val) + : "m" (*(uint32_t *)ptr)); + return val; +#else + uint8_t *b = (uint8_t *) ptr; + return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; +#endif +} + +static inline uint64_t ldq_raw(void *ptr) +{ + uint32_t a,b; + a = ldl_raw(ptr); + b = ldl_raw(ptr+4); + return (((uint64_t)a<<32)|b); +} + +static inline void stw_raw(void *ptr, int v) +{ +#if defined(__i386__) + asm volatile ("xchgb %b0, %h0\n" + "movw %w0, %1\n" + : "=q" (v) + : "m" (*(uint16_t *)ptr), "0" (v)); +#else + uint8_t *d = (uint8_t *) ptr; + d[0] = v >> 8; + d[1] = v; +#endif +} + +static inline void stl_raw(void *ptr, int v) +{ +#if defined(__i386__) || defined(__x86_64__) + asm volatile ("bswap %0\n" + "movl %0, %1\n" + : "=r" (v) + : "m" (*(uint32_t *)ptr), "0" (v)); +#else + uint8_t *d = (uint8_t *) ptr; + d[0] = v >> 24; + d[1] = v >> 16; + d[2] = v >> 8; + d[3] = v; +#endif +} + +static inline void stq_raw(void *ptr, uint64_t v) +{ + stl_raw(ptr, v >> 32); + stl_raw(ptr + 4, v); +} + +/* float access */ + +static inline float ldfl_raw(void *ptr) +{ + union { + float f; + uint32_t i; + } u; + u.i = ldl_raw(ptr); + return u.f; +} + +static inline void stfl_raw(void *ptr, float v) +{ + union { + float f; + uint32_t i; + } u; + u.f = v; + stl_raw(ptr, u.i); +} + +static inline double ldfq_raw(void *ptr) +{ + CPU_DoubleU u; + u.l.upper = ldl_raw(ptr); + u.l.lower = ldl_raw(ptr + 4); + return u.d; +} + +static inline void stfq_raw(void *ptr, double v) +{ + CPU_DoubleU u; + u.d = v; + stl_raw(ptr, u.l.upper); + stl_raw(ptr + 4, u.l.lower); +} + +#else + +static inline int lduw_raw(void *ptr) +{ + return *(uint16_t *)ptr; +} + +static inline int ldsw_raw(void *ptr) +{ + return *(int16_t *)ptr; +} + +static inline int ldl_raw(void *ptr) +{ + return *(uint32_t *)ptr; +} + +static inline uint64_t ldq_raw(void *ptr) +{ + return *(uint64_t *)ptr; +} + +static inline void stw_raw(void *ptr, int v) +{ + *(uint16_t *)ptr = v; +} + +static inline void stl_raw(void *ptr, int v) +{ + *(uint32_t *)ptr = v; +} + +static inline void stq_raw(void *ptr, uint64_t v) +{ + *(uint64_t *)ptr = v; +} + +/* float access */ + +static inline float ldfl_raw(void *ptr) +{ + return *(float *)ptr; +} + +static inline double ldfq_raw(void *ptr) +{ + return *(double *)ptr; +} + +static inline void stfl_raw(void *ptr, float v) +{ + *(float *)ptr = v; +} + +static inline void stfq_raw(void *ptr, double v) +{ + *(double *)ptr = v; +} +#endif + +/* MMU memory access macros */ + +#if defined(CONFIG_USER_ONLY) + +/* if user mode, no other memory access functions */ +#define ldub(p) ldub_raw(p) +#define ldsb(p) ldsb_raw(p) +#define lduw(p) lduw_raw(p) +#define ldsw(p) ldsw_raw(p) +#define ldl(p) ldl_raw(p) +#define ldq(p) ldq_raw(p) +#define ldfl(p) ldfl_raw(p) +#define ldfq(p) ldfq_raw(p) +#define stb(p, v) stb_raw(p, v) +#define stw(p, v) stw_raw(p, v) +#define stl(p, v) stl_raw(p, v) +#define stq(p, v) stq_raw(p, v) +#define stfl(p, v) stfl_raw(p, v) +#define stfq(p, v) stfq_raw(p, v) + +#define ldub_code(p) ldub_raw(p) +#define ldsb_code(p) ldsb_raw(p) +#define lduw_code(p) lduw_raw(p) +#define ldsw_code(p) ldsw_raw(p) +#define ldl_code(p) ldl_raw(p) + +#define ldub_kernel(p) ldub_raw(p) +#define ldsb_kernel(p) ldsb_raw(p) +#define lduw_kernel(p) lduw_raw(p) +#define ldsw_kernel(p) ldsw_raw(p) +#define ldl_kernel(p) ldl_raw(p) +#define ldfl_kernel(p) ldfl_raw(p) +#define ldfq_kernel(p) ldfq_raw(p) +#define stb_kernel(p, v) stb_raw(p, v) +#define stw_kernel(p, v) stw_raw(p, v) +#define stl_kernel(p, v) stl_raw(p, v) +#define stq_kernel(p, v) stq_raw(p, v) +#define stfl_kernel(p, v) stfl_raw(p, v) +#define stfq_kernel(p, vt) stfq_raw(p, v) + +#endif /* defined(CONFIG_USER_ONLY) */ + +/* page related stuff */ + +#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS) +#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1) +#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK) + +extern unsigned long qemu_real_host_page_size; +extern unsigned long qemu_host_page_bits; +extern unsigned long qemu_host_page_size; +extern unsigned long qemu_host_page_mask; + +#define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask) + +/* same as PROT_xxx */ +#define PAGE_READ 0x0001 +#define PAGE_WRITE 0x0002 +#define PAGE_EXEC 0x0004 +#define PAGE_BITS (PAGE_READ | PAGE_WRITE | PAGE_EXEC) +#define PAGE_VALID 0x0008 +/* original state of the write flag (used when tracking self-modifying + code */ +#define PAGE_WRITE_ORG 0x0010 + +void page_dump(FILE *f); +int page_get_flags(unsigned long address); +void page_set_flags(unsigned long start, unsigned long end, int flags); +void page_unprotect_range(uint8_t *data, unsigned long data_size); + +#define CPUState CPUX86State + +void cpu_dump_state(CPUState *env, FILE *f, + int (*cpu_fprintf)(FILE *f, const char *fmt, ...), + int flags); + +void cpu_abort(CPUState *env, const char *fmt, ...); +extern CPUState *cpu_single_env; +extern int code_copy_enabled; + +#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */ +#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */ +#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */ +#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */ +void cpu_interrupt(CPUState *s, int mask); +void cpu_reset_interrupt(CPUState *env, int mask); + +int cpu_breakpoint_insert(CPUState *env, target_ulong pc); +int cpu_breakpoint_remove(CPUState *env, target_ulong pc); +void cpu_single_step(CPUState *env, int enabled); +void cpu_reset(CPUState *s); +CPUState *cpu_init(void); +int main_loop(void); + +/* Return the physical page corresponding to a virtual one. Use it + only for debugging because no protection checks are done. Return -1 + if no page found. */ +target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr); + +#define CPU_LOG_TB_OUT_ASM (1 << 0) +#define CPU_LOG_TB_IN_ASM (1 << 1) +#define CPU_LOG_TB_OP (1 << 2) +#define CPU_LOG_TB_OP_OPT (1 << 3) +#define CPU_LOG_INT (1 << 4) +#define CPU_LOG_EXEC (1 << 5) +#define CPU_LOG_PCALL (1 << 6) +#define CPU_LOG_IOPORT (1 << 7) +#define CPU_LOG_TB_CPU (1 << 8) + +/* define log items */ +typedef struct CPULogItem { + int mask; + const char *name; + const char *help; +} CPULogItem; + +extern CPULogItem cpu_log_items[]; + +void cpu_set_log(int log_flags); +void cpu_set_log_filename(const char *filename); +int cpu_str_to_log_mask(const char *str); + +/* IO ports API */ + +/* NOTE: as these functions may be even used when there is an isa + brige on non x86 targets, we always defined them */ +#ifndef NO_CPU_IO_DEFS +void cpu_outb(CPUState *env, int addr, int val); +void cpu_outw(CPUState *env, int addr, int val); +void cpu_outl(CPUState *env, int addr, int val); +int cpu_inb(CPUState *env, int addr); +int cpu_inw(CPUState *env, int addr); +int cpu_inl(CPUState *env, int addr); +#endif + +/* memory API */ + +extern int phys_ram_size; +extern int phys_ram_fd; +extern uint8_t *phys_ram_base; +extern uint8_t *phys_ram_dirty; + +/* physical memory access */ +#define IO_MEM_NB_ENTRIES 256 +#define TLB_INVALID_MASK (1 << 3) +#define IO_MEM_SHIFT 4 + +#define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */ +#define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */ +#define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT) +#define IO_MEM_CODE (3 << IO_MEM_SHIFT) /* used internally, never use directly */ +#define IO_MEM_NOTDIRTY (4 << IO_MEM_SHIFT) /* used internally, never use directly */ + +typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value); +typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr); + +void cpu_register_physical_memory(target_phys_addr_t start_addr, + unsigned long size, + unsigned long phys_offset); +int cpu_register_io_memory(int io_index, + CPUReadMemoryFunc **mem_read, + CPUWriteMemoryFunc **mem_write, + void *opaque); +CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index); +CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index); + +void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, + int len, int is_write); +static inline void cpu_physical_memory_read(target_phys_addr_t addr, + uint8_t *buf, int len) +{ + cpu_physical_memory_rw(addr, buf, len, 0); +} +static inline void cpu_physical_memory_write(target_phys_addr_t addr, + const uint8_t *buf, int len) +{ + cpu_physical_memory_rw(addr, (uint8_t *)buf, len, 1); +} + +int cpu_memory_rw_debug(CPUState *env, target_ulong addr, + uint8_t *buf, int len, int is_write); + +/* read dirty bit (return 0 or 1) */ +static inline int cpu_physical_memory_is_dirty(target_ulong addr) +{ + return phys_ram_dirty[addr >> TARGET_PAGE_BITS]; +} + +static inline void cpu_physical_memory_set_dirty(target_ulong addr) +{ + phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 1; +} + +void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end); + +#endif /* CPU_ALL_H */ diff --git a/tools/ioemu/cpu-defs.h b/tools/ioemu/cpu-defs.h new file mode 100644 index 0000000000..388d4abdbb --- /dev/null +++ b/tools/ioemu/cpu-defs.h @@ -0,0 +1,95 @@ +/* + * common defines for all CPUs + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef CPU_DEFS_H +#define CPU_DEFS_H + +#include "config.h" +#include +#include +#include "osdep.h" + +#ifndef TARGET_LONG_BITS +#error TARGET_LONG_BITS must be defined before including this header +#endif + +#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) +#define HOST_LONG_BITS 64 +#else +#define HOST_LONG_BITS 32 +#endif + +#ifndef TARGET_PHYS_ADDR_BITS +#if TARGET_LONG_BITS >= HOST_LONG_BITS +#define TARGET_PHYS_ADDR_BITS TARGET_LONG_BITS +#else +#define TARGET_PHYS_ADDR_BITS HOST_LONG_BITS +#endif +#endif + +#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8) + +/* target_ulong is the type of a virtual address */ +#if TARGET_LONG_SIZE == 4 +typedef int32_t target_long; +typedef uint32_t target_ulong; +#elif TARGET_LONG_SIZE == 8 +typedef int64_t target_long; +typedef uint64_t target_ulong; +#else +#error TARGET_LONG_SIZE undefined +#endif + +/* target_phys_addr_t is the type of a physical address (its size can + be different from 'target_ulong'). We have sizeof(target_phys_addr) + = max(sizeof(unsigned long), + sizeof(size_of_target_physical_address)) because we must pass a + host pointer to memory operations in some cases */ + +#if TARGET_PHYS_ADDR_BITS == 32 +typedef uint32_t target_phys_addr_t; +#elif TARGET_PHYS_ADDR_BITS == 64 +typedef uint64_t target_phys_addr_t; +#else +#error TARGET_PHYS_ADDR_BITS undefined +#endif + +#define HOST_LONG_SIZE (HOST_LONG_BITS / 8) + +#define EXCP_INTERRUPT 256 /* async interruption */ +#define EXCP_HLT 257 /* hlt instruction reached */ +#define EXCP_DEBUG 258 /* cpu stopped after a breakpoint or singlestep */ + +#define MAX_BREAKPOINTS 32 + +#define CPU_TLB_SIZE 256 + +typedef struct CPUTLBEntry { + /* bit 31 to TARGET_PAGE_BITS : virtual address + bit TARGET_PAGE_BITS-1..IO_MEM_SHIFT : if non zero, memory io + zone number + bit 3 : indicates that the entry is invalid + bit 2..0 : zero + */ + target_ulong address; + /* addend to virtual address to get physical address */ + target_phys_addr_t addend; +} CPUTLBEntry; + +#endif diff --git a/tools/ioemu/cpu.h b/tools/ioemu/cpu.h new file mode 100644 index 0000000000..adeb5bdd93 --- /dev/null +++ b/tools/ioemu/cpu.h @@ -0,0 +1,69 @@ +/* + * i386 virtual CPU header + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef CPU_I386_H +#define CPU_I386_H + +#include "config.h" + +#ifdef TARGET_X86_64 +#define TARGET_LONG_BITS 64 +#else +#define TARGET_LONG_BITS 32 +#endif + +/* target supports implicit self modifying code */ +#define TARGET_HAS_SMC +/* support for self modifying code even if the modified instruction is + close to the modifying instruction */ +#define TARGET_HAS_PRECISE_SMC + +#include "cpu-defs.h" + +#if defined(__i386__) && !defined(CONFIG_SOFTMMU) +#define USE_CODE_COPY +#endif + +/* Empty for now */ +typedef struct CPUX86State { + uint32_t a20_mask; + int interrupt_request; + int send_event; +} CPUX86State; + +#ifndef IN_OP_I386 +void cpu_x86_outb(CPUX86State *env, int addr, int val); +void cpu_x86_outw(CPUX86State *env, int addr, int val); +void cpu_x86_outl(CPUX86State *env, int addr, int val); +int cpu_x86_inb(CPUX86State *env, int addr); +int cpu_x86_inw(CPUX86State *env, int addr); +int cpu_x86_inl(CPUX86State *env, int addr); +#endif + +CPUX86State *cpu_x86_init(void); +int cpu_x86_exec(CPUX86State *s); +void cpu_x86_close(CPUX86State *s); +int cpu_get_pic_interrupt(CPUX86State *s); +/* MSDOS compatibility mode FPU exception support */ +void cpu_set_ferr(CPUX86State *s); + +#define TARGET_PAGE_BITS 12 +#include "cpu-all.h" + +#endif /* CPU_I386_H */ diff --git a/tools/ioemu/create_keysym_header.sh b/tools/ioemu/create_keysym_header.sh new file mode 100644 index 0000000000..87b05e00ad --- /dev/null +++ b/tools/ioemu/create_keysym_header.sh @@ -0,0 +1,77 @@ +#!/bin/sh + +# QEMU keysym adapter: create a header file to link the name to its keysym +# +# Copyright (c) 2004,2005 Johannes E. Schindelin +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +type="$1" +cflags="$2" +if [ -z "$cflags" ]; then + echo "Usage: $0 vnc|sdl cflags" + exit 1 +fi + + +case "$type" in +vnc) + ignore_case='' + header=rfb/keysym.h + keysym_t=rfbKeySym + pattern='^#define[ ]*XK_\([^ ]*\)[ ].*$' + replacement='#ifdef XK_\1\n{\"\1\", XK_\1},\n#endif' + extra_replace='cat' + extra_sort='cat' + ;; +sdl) + ignore_case='-f' + header=SDL_keysym.h + keysym_t=int + pattern='^[ ]*SDLK_\([^ ]*\)[ ]*=.*$' + replacement='{\"\1\", SDLK_\1},' + extra_replace='sed -e s/{"\([RL]\)\(SUPER\|META\|ALT\|CONTROL\|SHIFT\)/{"\2_\1/ -e s/{"\([RL]\)CTRL/{"CONTROL_\1/ -e s/{"\(PAGE\)\(UP\|DOWN\)/{"\1_\2/ -e s/{"\(KP\)\([0-9]\)/{"\1_\2/ -e s/{"KP_MINUS/{"KP_SUBTRACT/ -e s/{"KP_PLUS/{"KP_ADD/ -e s/{"KP_PERIOD/{"KP_DECIMAL/ -e s/{"\(LEFT\|RIGHT\)\(PAREN\|BRACKET\)/{"\2\1/ -e s/{"EXCLAIM/{"EXCLAM/ -e s/{"\(CAPS\|NUM\)\(LOCK\)/{"\1_\2/ -e s/{"SCROLLOCK/{"SCROLL_LOCK/ -e s/{"KP_EQUALS/{"KP_EQUAL/ -e s/{"SYSREQ/{"SYS_REQ/ -e s/{"QUOTE"/{"APOSTROPHE"/ -e s/{"BACKQUOTE/{"GRAVE/ -e s/{"EQUALS/{"EQUAL/ -e s/{"EURO/{"EUROSIGN/ -e s/{"COMPOSE/{"MULTI_KEY/ -e s/{"MODE/{"MODE_SWITCH/ -e s/{"HASH/{"NUMBERSIGN/ -e s/{"WORLD_68/{"ADIAERESIS/ -e s/{"WORLD_86/{"ODIAERESIS/ -e s/{"WORLD_92/{"UDIAERESIS/ -e s/{"WORLD_63/{"SSHARP/ -e s/{"WORLD_20/{"ACUTE/ -e s/{"CARET/{"ASCIICIRCUM/' + extra_sort='sort -f' + ;; +*) echo "Unknown type: $type is neither vnc nor sdl"; exit 1;; +esac + +outfile=keysym_adapter_"$type".h + +echo "typedef struct {" > $outfile +echo " const char* name;" >> $outfile +echo " $keysym_t keysym;" >> $outfile +echo "} name2keysym_t;" >> $outfile +echo "static name2keysym_t name2keysym[]={" >> $outfile + +for path in $(echo "$cflags" | sed "s/-I/ /g"); do + if [ -f $path/$header ]; then + cat $path/$header + fi +done | tr "\011" " " | LC_ALL=C sort $ignore_case | uniq | \ +sed -n -e "s/$pattern/$replacement/p" | $extra_replace | \ +LC_ALL=C $extra_sort >> $outfile + +echo "{0,0}};" >> $outfile + +if [ -n "$ignore_case" ]; then +echo "#define KEYBOARD_IGNORE_CASE" >> $outfile +fi + + diff --git a/tools/ioemu/exec-all.h b/tools/ioemu/exec-all.h new file mode 100644 index 0000000000..ac0533982d --- /dev/null +++ b/tools/ioemu/exec-all.h @@ -0,0 +1,579 @@ +/* + * internal execution defines for qemu + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* allow to see translation results - the slowdown should be negligible, so we leave it */ +#define DEBUG_DISAS + +#ifndef glue +#define xglue(x, y) x ## y +#define glue(x, y) xglue(x, y) +#define stringify(s) tostring(s) +#define tostring(s) #s +#endif + +#if GCC_MAJOR < 3 +#define __builtin_expect(x, n) (x) +#endif + +#ifdef __i386__ +#define REGPARM(n) __attribute((regparm(n))) +#else +#define REGPARM(n) +#endif + +/* is_jmp field values */ +#define DISAS_NEXT 0 /* next instruction can be analyzed */ +#define DISAS_JUMP 1 /* only pc was modified dynamically */ +#define DISAS_UPDATE 2 /* cpu state was modified dynamically */ +#define DISAS_TB_JUMP 3 /* only pc was modified statically */ + +struct TranslationBlock; + +/* XXX: make safe guess about sizes */ +#define MAX_OP_PER_INSTR 32 +#define OPC_BUF_SIZE 512 +#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR) + +#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3) + +extern uint16_t gen_opc_buf[OPC_BUF_SIZE]; +extern uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE]; +extern uint32_t gen_opc_pc[OPC_BUF_SIZE]; +extern uint32_t gen_opc_npc[OPC_BUF_SIZE]; +extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE]; +extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; + +typedef void (GenOpFunc)(void); +typedef void (GenOpFunc1)(long); +typedef void (GenOpFunc2)(long, long); +typedef void (GenOpFunc3)(long, long, long); + +#if defined(TARGET_I386) + +void optimize_flags_init(void); + +#endif + +extern FILE *logfile; +extern int loglevel; + +int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb); +int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb); +void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf); +int cpu_gen_code(CPUState *env, struct TranslationBlock *tb, + int max_code_size, int *gen_code_size_ptr); +int cpu_restore_state(struct TranslationBlock *tb, + CPUState *env, unsigned long searched_pc, + void *puc); +int cpu_gen_code_copy(CPUState *env, struct TranslationBlock *tb, + int max_code_size, int *gen_code_size_ptr); +int cpu_restore_state_copy(struct TranslationBlock *tb, + CPUState *env, unsigned long searched_pc, + void *puc); +void cpu_resume_from_signal(CPUState *env1, void *puc); +void cpu_exec_init(void); +int page_unprotect(unsigned long address, unsigned long pc, void *puc); +void tb_invalidate_phys_page_range(target_ulong start, target_ulong end, + int is_cpu_write_access); +void tb_invalidate_page_range(target_ulong start, target_ulong end); +void tlb_flush_page(CPUState *env, target_ulong addr); +void tlb_flush(CPUState *env, int flush_global); +int tlb_set_page(CPUState *env, target_ulong vaddr, + target_phys_addr_t paddr, int prot, + int is_user, int is_softmmu); + +#define CODE_GEN_MAX_SIZE 65536 +#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */ + +#define CODE_GEN_HASH_BITS 15 +#define CODE_GEN_HASH_SIZE (1 << CODE_GEN_HASH_BITS) + +#define CODE_GEN_PHYS_HASH_BITS 15 +#define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS) + +/* maximum total translate dcode allocated */ + +/* NOTE: the translated code area cannot be too big because on some + archs the range of "fast" function calls is limited. Here is a + summary of the ranges: + + i386 : signed 32 bits + arm : signed 26 bits + ppc : signed 24 bits + sparc : signed 32 bits + alpha : signed 23 bits +*/ + +#if defined(__alpha__) +#define CODE_GEN_BUFFER_SIZE (2 * 1024 * 1024) +#elif defined(__powerpc__) +#define CODE_GEN_BUFFER_SIZE (6 * 1024 * 1024) +#else +#define CODE_GEN_BUFFER_SIZE (8 * 1024 * 1024) +#endif + +//#define CODE_GEN_BUFFER_SIZE (128 * 1024) + +/* estimated block size for TB allocation */ +/* XXX: use a per code average code fragment size and modulate it + according to the host CPU */ +#if defined(CONFIG_SOFTMMU) +#define CODE_GEN_AVG_BLOCK_SIZE 128 +#else +#define CODE_GEN_AVG_BLOCK_SIZE 64 +#endif + +#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE) + +#if defined(__powerpc__) +#define USE_DIRECT_JUMP +#endif +#if defined(__i386__) && !defined(_WIN32) +#define USE_DIRECT_JUMP +#endif + +typedef struct TranslationBlock { + target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */ + target_ulong cs_base; /* CS base for this block */ + unsigned int flags; /* flags defining in which context the code was generated */ + uint16_t size; /* size of target code for this block (1 <= + size <= TARGET_PAGE_SIZE) */ + uint16_t cflags; /* compile flags */ +#define CF_CODE_COPY 0x0001 /* block was generated in code copy mode */ +#define CF_TB_FP_USED 0x0002 /* fp ops are used in the TB */ +#define CF_FP_USED 0x0004 /* fp ops are used in the TB or in a chained TB */ +#define CF_SINGLE_INSN 0x0008 /* compile only a single instruction */ + + uint8_t *tc_ptr; /* pointer to the translated code */ + struct TranslationBlock *hash_next; /* next matching tb for virtual address */ + /* next matching tb for physical address. */ + struct TranslationBlock *phys_hash_next; + /* first and second physical page containing code. The lower bit + of the pointer tells the index in page_next[] */ + struct TranslationBlock *page_next[2]; + target_ulong page_addr[2]; + + /* the following data are used to directly call another TB from + the code of this one. */ + uint16_t tb_next_offset[2]; /* offset of original jump target */ +#ifdef USE_DIRECT_JUMP + uint16_t tb_jmp_offset[4]; /* offset of jump instruction */ +#else + uint32_t tb_next[2]; /* address of jump generated code */ +#endif + /* list of TBs jumping to this one. This is a circular list using + the two least significant bits of the pointers to tell what is + the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 = + jmp_first */ + struct TranslationBlock *jmp_next[2]; + struct TranslationBlock *jmp_first; +} TranslationBlock; + +static inline unsigned int tb_hash_func(unsigned long pc) +{ + return pc & (CODE_GEN_HASH_SIZE - 1); +} + +static inline unsigned int tb_phys_hash_func(unsigned long pc) +{ + return pc & (CODE_GEN_PHYS_HASH_SIZE - 1); +} + +TranslationBlock *tb_alloc(unsigned long pc); +void tb_flush(CPUState *env); +void tb_link(TranslationBlock *tb); +void tb_link_phys(TranslationBlock *tb, + target_ulong phys_pc, target_ulong phys_page2); + +extern TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE]; +extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; + +extern uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE]; +extern uint8_t *code_gen_ptr; + +/* find a translation block in the translation cache. If not found, + return NULL and the pointer to the last element of the list in pptb */ +static inline TranslationBlock *tb_find(TranslationBlock ***pptb, + target_ulong pc, + target_ulong cs_base, + unsigned int flags) +{ + TranslationBlock **ptb, *tb; + unsigned int h; + + h = tb_hash_func(pc); + ptb = &tb_hash[h]; + for(;;) { + tb = *ptb; + if (!tb) + break; + if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags) + return tb; + ptb = &tb->hash_next; + } + *pptb = ptb; + return NULL; +} + + +#if defined(USE_DIRECT_JUMP) + +#if defined(__powerpc__) +static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr) +{ + uint32_t val, *ptr; + + /* patch the branch destination */ + ptr = (uint32_t *)jmp_addr; + val = *ptr; + val = (val & ~0x03fffffc) | ((addr - jmp_addr) & 0x03fffffc); + *ptr = val; + /* flush icache */ + asm volatile ("dcbst 0,%0" : : "r"(ptr) : "memory"); + asm volatile ("sync" : : : "memory"); + asm volatile ("icbi 0,%0" : : "r"(ptr) : "memory"); + asm volatile ("sync" : : : "memory"); + asm volatile ("isync" : : : "memory"); +} +#elif defined(__i386__) +static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr) +{ + /* patch the branch destination */ + *(uint32_t *)jmp_addr = addr - (jmp_addr + 4); + /* no need to flush icache explicitely */ +} +#endif + +static inline void tb_set_jmp_target(TranslationBlock *tb, + int n, unsigned long addr) +{ + unsigned long offset; + + offset = tb->tb_jmp_offset[n]; + tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr); + offset = tb->tb_jmp_offset[n + 2]; + if (offset != 0xffff) + tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr); +} + +#else + +/* set the jump target */ +static inline void tb_set_jmp_target(TranslationBlock *tb, + int n, unsigned long addr) +{ + tb->tb_next[n] = addr; +} + +#endif + +static inline void tb_add_jump(TranslationBlock *tb, int n, + TranslationBlock *tb_next) +{ + /* NOTE: this test is only needed for thread safety */ + if (!tb->jmp_next[n]) { + /* patch the native jump address */ + tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr); + + /* add in TB jmp circular list */ + tb->jmp_next[n] = tb_next->jmp_first; + tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n)); + } +} + +TranslationBlock *tb_find_pc(unsigned long pc_ptr); + +#ifndef offsetof +#define offsetof(type, field) ((size_t) &((type *)0)->field) +#endif + +#if defined(_WIN32) +#define ASM_DATA_SECTION ".section \".data\"\n" +#define ASM_PREVIOUS_SECTION ".section .text\n" +#elif defined(__APPLE__) +#define ASM_DATA_SECTION ".data\n" +#define ASM_PREVIOUS_SECTION ".text\n" +#define ASM_NAME(x) "_" #x +#else +#define ASM_DATA_SECTION ".section \".data\"\n" +#define ASM_PREVIOUS_SECTION ".previous\n" +#define ASM_NAME(x) stringify(x) +#endif + +#if defined(__powerpc__) + +/* we patch the jump instruction directly */ +#define JUMP_TB(opname, tbparam, n, eip)\ +do {\ + asm volatile (ASM_DATA_SECTION\ + ASM_NAME(__op_label) #n "." ASM_NAME(opname) ":\n"\ + ".long 1f\n"\ + ASM_PREVIOUS_SECTION \ + "b " ASM_NAME(__op_jmp) #n "\n"\ + "1:\n");\ + T0 = (long)(tbparam) + (n);\ + EIP = eip;\ + EXIT_TB();\ +} while (0) + +#define JUMP_TB2(opname, tbparam, n)\ +do {\ + asm volatile ("b " ASM_NAME(__op_jmp) #n "\n");\ +} while (0) + +#elif defined(__i386__) && defined(USE_DIRECT_JUMP) + +/* we patch the jump instruction directly */ +#define JUMP_TB(opname, tbparam, n, eip)\ +do {\ + asm volatile (".section .data\n"\ + ASM_NAME(__op_label) #n "." ASM_NAME(opname) ":\n"\ + ".long 1f\n"\ + ASM_PREVIOUS_SECTION \ + "jmp " ASM_NAME(__op_jmp) #n "\n"\ + "1:\n");\ + T0 = (long)(tbparam) + (n);\ + EIP = eip;\ + EXIT_TB();\ +} while (0) + +#define JUMP_TB2(opname, tbparam, n)\ +do {\ + asm volatile ("jmp " ASM_NAME(__op_jmp) #n "\n");\ +} while (0) + +#else + +/* jump to next block operations (more portable code, does not need + cache flushing, but slower because of indirect jump) */ +#define JUMP_TB(opname, tbparam, n, eip)\ +do {\ + static void __attribute__((unused)) *__op_label ## n = &&label ## n;\ + static void __attribute__((unused)) *dummy ## n = &&dummy_label ## n;\ + goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\ +label ## n:\ + T0 = (long)(tbparam) + (n);\ + EIP = eip;\ +dummy_label ## n:\ + EXIT_TB();\ +} while (0) + +/* second jump to same destination 'n' */ +#define JUMP_TB2(opname, tbparam, n)\ +do {\ + goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n - 2]);\ +} while (0) + +#endif + +extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; +extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; +extern void *io_mem_opaque[IO_MEM_NB_ENTRIES]; + +#ifdef __powerpc__ +static inline int testandset (int *p) +{ + int ret; + __asm__ __volatile__ ( + "0: lwarx %0,0,%1\n" + " xor. %0,%3,%0\n" + " bne 1f\n" + " stwcx. %2,0,%1\n" + " bne- 0b\n" + "1: " + : "=&r" (ret) + : "r" (p), "r" (1), "r" (0) + : "cr0", "memory"); + return ret; +} +#endif + +#ifdef __i386__ +static inline int testandset (int *p) +{ + char ret; + long int readval; + + __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (1), "m" (*p), "a" (0) + : "memory"); + return ret; +} +#endif + +#ifdef __x86_64__ +static inline int testandset (int *p) +{ + char ret; + int readval; + + __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0" + : "=q" (ret), "=m" (*p), "=a" (readval) + : "r" (1), "m" (*p), "a" (0) + : "memory"); + return ret; +} +#endif + +#ifdef __s390__ +static inline int testandset (int *p) +{ + int ret; + + __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n" + " jl 0b" + : "=&d" (ret) + : "r" (1), "a" (p), "0" (*p) + : "cc", "memory" ); + return ret; +} +#endif + +#ifdef __alpha__ +static inline int testandset (int *p) +{ + int ret; + unsigned long one; + + __asm__ __volatile__ ("0: mov 1,%2\n" + " ldl_l %0,%1\n" + " stl_c %2,%1\n" + " beq %2,1f\n" + ".subsection 2\n" + "1: br 0b\n" + ".previous" + : "=r" (ret), "=m" (*p), "=r" (one) + : "m" (*p)); + return ret; +} +#endif + +#ifdef __sparc__ +static inline int testandset (int *p) +{ + int ret; + + __asm__ __volatile__("ldstub [%1], %0" + : "=r" (ret) + : "r" (p) + : "memory"); + + return (ret ? 1 : 0); +} +#endif + +#ifdef __arm__ +static inline int testandset (int *spinlock) +{ + register unsigned int ret; + __asm__ __volatile__("swp %0, %1, [%2]" + : "=r"(ret) + : "0"(1), "r"(spinlock)); + + return ret; +} +#endif + +#ifdef __mc68000 +static inline int testandset (int *p) +{ + char ret; + __asm__ __volatile__("tas %1; sne %0" + : "=r" (ret) + : "m" (p) + : "cc","memory"); + return ret == 0; +} +#endif + +typedef int spinlock_t; + +#define SPIN_LOCK_UNLOCKED 0 + +#if defined(CONFIG_USER_ONLY) +static inline void spin_lock(spinlock_t *lock) +{ + while (testandset(lock)); +} + +static inline void spin_unlock(spinlock_t *lock) +{ + *lock = 0; +} + +static inline int spin_trylock(spinlock_t *lock) +{ + return !testandset(lock); +} +#else +static inline void spin_lock(spinlock_t *lock) +{ +} + +static inline void spin_unlock(spinlock_t *lock) +{ +} + +static inline int spin_trylock(spinlock_t *lock) +{ + return 1; +} +#endif + +extern spinlock_t tb_lock; + +extern int tb_invalidated_flag; + +#if !defined(CONFIG_USER_ONLY) + +void tlb_fill(unsigned long addr, int is_write, int is_user, + void *retaddr); + +#define ACCESS_TYPE 3 +#define MEMSUFFIX _code +#define env cpu_single_env + +#undef ACCESS_TYPE +#undef MEMSUFFIX +#undef env + +#endif + +#if defined(CONFIG_USER_ONLY) +static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) +{ + return addr; +} +#else +/* NOTE: this function can trigger an exception */ +/* NOTE2: the returned address is not exactly the physical address: it + is the offset relative to phys_ram_base */ +/* XXX: i386 target specific */ +static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) +{ + return addr; +} +#endif + +//#define DEBUG_UNUSED_IOPORT +//#define DEBUG_IOPORT +#define TARGET_VMX + diff --git a/tools/ioemu/exec.c b/tools/ioemu/exec.c new file mode 100644 index 0000000000..c49975c3c1 --- /dev/null +++ b/tools/ioemu/exec.c @@ -0,0 +1,461 @@ +/* + * virtual page mapping and translated block handling + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include "config.h" +#ifdef _WIN32 +#include +#else +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "cpu.h" +#include "exec-all.h" + +//#define DEBUG_TB_INVALIDATE +//#define DEBUG_FLUSH +//#define DEBUG_TLB + +/* make various TB consistency checks */ +//#define DEBUG_TB_CHECK +//#define DEBUG_TLB_CHECK + +/* threshold to flush the translated code buffer */ +#define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE) + +#define SMC_BITMAP_USE_THRESHOLD 10 + +#define MMAP_AREA_START 0x00000000 +#define MMAP_AREA_END 0xa8000000 + +TranslationBlock tbs[CODE_GEN_MAX_BLOCKS]; +TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE]; +TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; +int nb_tbs; +/* any access to the tbs or the page table must use this lock */ +spinlock_t tb_lock = SPIN_LOCK_UNLOCKED; + +uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE]; +uint8_t *code_gen_ptr; + +int phys_ram_size; +int phys_ram_fd; +uint8_t *phys_ram_base; +uint8_t *phys_ram_dirty; + +typedef struct PageDesc { + /* list of TBs intersecting this ram page */ + TranslationBlock *first_tb; + /* in order to optimize self modifying code, we count the number + of lookups we do to a given page to use a bitmap */ + unsigned int code_write_count; + uint8_t *code_bitmap; +#if defined(CONFIG_USER_ONLY) + unsigned long flags; +#endif +} PageDesc; + +typedef struct PhysPageDesc { + /* offset in host memory of the page + io_index in the low 12 bits */ + unsigned long phys_offset; +} PhysPageDesc; + +typedef struct VirtPageDesc { + /* physical address of code page. It is valid only if 'valid_tag' + matches 'virt_valid_tag' */ + target_ulong phys_addr; + unsigned int valid_tag; +#if !defined(CONFIG_SOFTMMU) + /* original page access rights. It is valid only if 'valid_tag' + matches 'virt_valid_tag' */ + unsigned int prot; +#endif +} VirtPageDesc; + +#define L2_BITS 10 +#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS) + +#define L1_SIZE (1 << L1_BITS) +#define L2_SIZE (1 << L2_BITS) + +unsigned long qemu_real_host_page_size; +unsigned long qemu_host_page_bits; +unsigned long qemu_host_page_size; +unsigned long qemu_host_page_mask; + +/* io memory support */ +CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4]; +CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4]; +void *io_mem_opaque[IO_MEM_NB_ENTRIES]; +static int io_mem_nb = 1; + +/* log support */ +char *logfilename = "/tmp/qemu.log"; +FILE *logfile; +int loglevel; + +void cpu_exec_init(void) +{ + /* alloc dirty bits array */ + phys_ram_dirty = qemu_malloc(phys_ram_size >> TARGET_PAGE_BITS); +} + +/* enable or disable low levels log */ +void cpu_set_log(int log_flags) +{ + loglevel = log_flags; + if (loglevel && !logfile) { + logfile = fopen(logfilename, "w"); + if (!logfile) { + perror(logfilename); + _exit(1); + } +#if !defined(CONFIG_SOFTMMU) + /* must avoid mmap() usage of glibc by setting a buffer "by hand" */ + { + static uint8_t logfile_buf[4096]; + setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf)); + } +#else + setvbuf(logfile, NULL, _IOLBF, 0); +#endif + } +} + +void cpu_set_log_filename(const char *filename) +{ + logfilename = strdup(filename); +} + +/* mask must never be zero, except for A20 change call */ +void cpu_interrupt(CPUState *env, int mask) +{ + env->interrupt_request |= mask; +} + +void cpu_reset_interrupt(CPUState *env, int mask) +{ + env->interrupt_request &= ~mask; +} + +CPULogItem cpu_log_items[] = { + { CPU_LOG_TB_OUT_ASM, "out_asm", + "show generated host assembly code for each compiled TB" }, + { CPU_LOG_TB_IN_ASM, "in_asm", + "show target assembly code for each compiled TB" }, + { CPU_LOG_TB_OP, "op", + "show micro ops for each compiled TB (only usable if 'in_asm' used)" }, +#ifdef TARGET_I386 + { CPU_LOG_TB_OP_OPT, "op_opt", + "show micro ops after optimization for each compiled TB" }, +#endif + { CPU_LOG_INT, "int", + "show interrupts/exceptions in short format" }, + { CPU_LOG_EXEC, "exec", + "show trace before each executed TB (lots of logs)" }, + { CPU_LOG_TB_CPU, "cpu", + "show CPU state before bloc translation" }, +#ifdef TARGET_I386 + { CPU_LOG_PCALL, "pcall", + "show protected mode far calls/returns/exceptions" }, +#endif +#ifdef DEBUG_IOPORT + { CPU_LOG_IOPORT, "ioport", + "show all i/o ports accesses" }, +#endif + { 0, NULL, NULL }, +}; + +static int cmp1(const char *s1, int n, const char *s2) +{ + if (strlen(s2) != n) + return 0; + return memcmp(s1, s2, n) == 0; +} + +/* takes a comma separated list of log masks. Return 0 if error. */ +int cpu_str_to_log_mask(const char *str) +{ + CPULogItem *item; + int mask; + const char *p, *p1; + + p = str; + mask = 0; + for(;;) { + p1 = strchr(p, ','); + if (!p1) + p1 = p + strlen(p); + if(cmp1(p,p1-p,"all")) { + for(item = cpu_log_items; item->mask != 0; item++) { + mask |= item->mask; + } + } else { + for(item = cpu_log_items; item->mask != 0; item++) { + if (cmp1(p, p1 - p, item->name)) + goto found; + } + return 0; + } + found: + mask |= item->mask; + if (*p1 != ',') + break; + p = p1 + 1; + } + return mask; +} + +void cpu_abort(CPUState *env, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "qemu: fatal: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + abort(); +} + + +/* XXX: Simple implementation. Fix later */ +#define MAX_MMIO 32 +struct mmio_space { + target_phys_addr_t start; + unsigned long size; + unsigned long io_index; +} mmio[MAX_MMIO]; +unsigned long mmio_cnt; + +/* register physical memory. 'size' must be a multiple of the target + page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an + io memory page */ +void cpu_register_physical_memory(target_phys_addr_t start_addr, + unsigned long size, + unsigned long phys_offset) +{ + if (mmio_cnt == MAX_MMIO) { + fprintf(logfile, "too many mmio regions\n"); + exit(-1); + } + mmio[mmio_cnt].io_index = phys_offset; + mmio[mmio_cnt].start = start_addr; + mmio[mmio_cnt++].size = size; +} + +/* mem_read and mem_write are arrays of functions containing the + function to access byte (index 0), word (index 1) and dword (index + 2). All functions must be supplied. If io_index is non zero, the + corresponding io zone is modified. If it is zero, a new io zone is + allocated. The return value can be used with + cpu_register_physical_memory(). (-1) is returned if error. */ +int cpu_register_io_memory(int io_index, + CPUReadMemoryFunc **mem_read, + CPUWriteMemoryFunc **mem_write, + void *opaque) +{ + int i; + + if (io_index <= 0) { + if (io_index >= IO_MEM_NB_ENTRIES) + return -1; + io_index = io_mem_nb++; + } else { + if (io_index >= IO_MEM_NB_ENTRIES) + return -1; + } + + for(i = 0;i < 3; i++) { + io_mem_read[io_index][i] = mem_read[i]; + io_mem_write[io_index][i] = mem_write[i]; + } + io_mem_opaque[io_index] = opaque; + return io_index << IO_MEM_SHIFT; +} + +CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index) +{ + return io_mem_write[io_index >> IO_MEM_SHIFT]; +} + +CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index) +{ + return io_mem_read[io_index >> IO_MEM_SHIFT]; +} + +/* physical memory access (slow version, mainly for debug) */ +#if defined(CONFIG_USER_ONLY) +void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, + int len, int is_write) +{ + int l, flags; + target_ulong page; + + while (len > 0) { + page = addr & TARGET_PAGE_MASK; + l = (page + TARGET_PAGE_SIZE) - addr; + if (l > len) + l = len; + flags = page_get_flags(page); + if (!(flags & PAGE_VALID)) + return; + if (is_write) { + if (!(flags & PAGE_WRITE)) + return; + memcpy((uint8_t *)addr, buf, len); + } else { + if (!(flags & PAGE_READ)) + return; + memcpy(buf, (uint8_t *)addr, len); + } + len -= l; + buf += l; + addr += l; + } +} +#else + +int iomem_index(target_phys_addr_t addr) +{ + int i; + + for (i = 0; i < mmio_cnt; i++) { + unsigned long start, end; + + start = mmio[i].start; + end = mmio[i].start + mmio[i].size; + + if ((addr >= start) && (addr <= end)){ + return (mmio[i].io_index >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1); + } + } + return 0; +} + +void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, + int len, int is_write) +{ + int l, io_index; + uint8_t *ptr; + uint32_t val; + target_phys_addr_t page; + unsigned long pd; + + while (len > 0) { + page = addr & TARGET_PAGE_MASK; + l = (page + TARGET_PAGE_SIZE) - addr; + if (l > len) + l = len; + + pd = page; + io_index = iomem_index(page); + if (is_write) { + if (io_index) { + if (l >= 4 && ((addr & 3) == 0)) { + /* 32 bit read access */ + val = ldl_raw(buf); + io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val); + l = 4; + } else if (l >= 2 && ((addr & 1) == 0)) { + /* 16 bit read access */ + val = lduw_raw(buf); + io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val); + l = 2; + } else { + /* 8 bit access */ + val = ldub_raw(buf); + io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val); + l = 1; + } + } else { + unsigned long addr1; + + addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); + /* RAM case */ + ptr = phys_ram_base + addr1; + memcpy(ptr, buf, l); + } + } else { + if (io_index) { + if (l >= 4 && ((addr & 3) == 0)) { + /* 32 bit read access */ + val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr); + stl_raw(buf, val); + l = 4; + } else if (l >= 2 && ((addr & 1) == 0)) { + /* 16 bit read access */ + val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr); + stw_raw(buf, val); + l = 2; + } else { + /* 8 bit access */ + val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr); + stb_raw(buf, val); + l = 1; + } + } else { + /* RAM case */ + ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + + (addr & ~TARGET_PAGE_MASK); + memcpy(buf, ptr, l); + } + } + len -= l; + buf += l; + addr += l; + } +} +#endif + +/* virtual memory access for debug */ +int cpu_memory_rw_debug(CPUState *env, target_ulong addr, + uint8_t *buf, int len, int is_write) +{ + int l; + target_ulong page, phys_addr; + + while (len > 0) { + page = addr & TARGET_PAGE_MASK; + phys_addr = cpu_get_phys_page_debug(env, page); + /* if no physical page mapped, return an error */ + if (phys_addr == -1) + return -1; + l = (page + TARGET_PAGE_SIZE) - addr; + if (l > len) + l = len; + cpu_physical_memory_rw(phys_addr + (addr & ~TARGET_PAGE_MASK), + buf, l, is_write); + len -= l; + buf += l; + addr += l; + } + return 0; +} + +void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end) +{ +} diff --git a/tools/ioemu/font/vga.bitmap.h b/tools/ioemu/font/vga.bitmap.h deleted file mode 100644 index e82dd629e6..0000000000 --- a/tools/ioemu/font/vga.bitmap.h +++ /dev/null @@ -1,288 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: vga.bitmap.h,v 1.4 2002/05/25 14:22:53 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -typedef struct { - unsigned char data[16]; - } bx_fontcharbitmap_t; - -static const bx_fontcharbitmap_t bx_vgafont[256] = { -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xa5, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xdb, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x36, 0x7f, 0x7f, 0x7f, 0x7f, 0x3e, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x3e, 0x7f, 0x3e, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff }}, -{{ 0x00, 0x00, 0x78, 0x60, 0x70, 0x58, 0x1e, 0x33, 0x33, 0x33, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0xfc, 0xcc, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x0f, 0x07, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0xfe, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xe6, 0xe7, 0x67, 0x03, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7f, 0x7c, 0x78, 0x70, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0xfe, 0xdb, 0xdb, 0xdb, 0xde, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x3e, 0x63, 0x06, 0x1c, 0x36, 0x63, 0x63, 0x36, 0x1c, 0x30, 0x63, 0x3e, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x7f, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0x7f, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x36, 0x7f, 0x36, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x1c, 0x3e, 0x3e, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x3e, 0x3e, 0x1c, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x36, 0x36, 0x7f, 0x36, 0x36, 0x36, 0x7f, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x18, 0x18, 0x3e, 0x63, 0x43, 0x03, 0x3e, 0x60, 0x60, 0x61, 0x63, 0x3e, 0x18, 0x18, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x43, 0x63, 0x30, 0x18, 0x0c, 0x06, 0x63, 0x61, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x1c, 0x36, 0x36, 0x1c, 0x6e, 0x3b, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x0c, 0x0c, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x1c, 0x36, 0x63, 0x63, 0x6b, 0x6b, 0x63, 0x63, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x18, 0x1c, 0x1e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3e, 0x63, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3e, 0x63, 0x60, 0x60, 0x3c, 0x60, 0x60, 0x60, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x30, 0x38, 0x3c, 0x36, 0x33, 0x7f, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x7f, 0x03, 0x03, 0x03, 0x3f, 0x60, 0x60, 0x60, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x1c, 0x06, 0x03, 0x03, 0x3f, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x7f, 0x63, 0x60, 0x60, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x7e, 0x60, 0x60, 0x60, 0x30, 0x1e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x30, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x7b, 0x7b, 0x7b, 0x3b, 0x03, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x08, 0x1c, 0x36, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3f, 0x66, 0x66, 0x66, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3f, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3c, 0x66, 0x43, 0x03, 0x03, 0x03, 0x03, 0x43, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x1f, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x1f, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x7f, 0x66, 0x46, 0x16, 0x1e, 0x16, 0x06, 0x46, 0x66, 0x7f, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x7f, 0x66, 0x46, 0x16, 0x1e, 0x16, 0x06, 0x06, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3c, 0x66, 0x43, 0x03, 0x03, 0x7b, 0x63, 0x63, 0x66, 0x5c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x33, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x67, 0x66, 0x66, 0x36, 0x1e, 0x1e, 0x36, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7f, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x63, 0x77, 0x7f, 0x7f, 0x6b, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x63, 0x67, 0x6f, 0x7f, 0x7b, 0x73, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3f, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x06, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x6b, 0x7b, 0x3e, 0x30, 0x70, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3f, 0x66, 0x66, 0x66, 0x3e, 0x36, 0x66, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x06, 0x1c, 0x30, 0x60, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x6b, 0x6b, 0x6b, 0x7f, 0x77, 0x36, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x63, 0x63, 0x36, 0x3e, 0x1c, 0x1c, 0x3e, 0x36, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x7f, 0x63, 0x61, 0x30, 0x18, 0x0c, 0x06, 0x43, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x08, 0x1c, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00 }}, -{{ 0x0c, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x07, 0x06, 0x06, 0x1e, 0x36, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x03, 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x38, 0x30, 0x30, 0x3c, 0x36, 0x33, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x7f, 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x1c, 0x36, 0x26, 0x06, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3e, 0x30, 0x33, 0x1e, 0x00 }}, -{{ 0x00, 0x00, 0x07, 0x06, 0x06, 0x36, 0x6e, 0x66, 0x66, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x18, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x60, 0x60, 0x00, 0x70, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x3c, 0x00 }}, -{{ 0x00, 0x00, 0x07, 0x06, 0x06, 0x66, 0x36, 0x1e, 0x1e, 0x36, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x7f, 0x6b, 0x6b, 0x6b, 0x6b, 0x63, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x0f, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3e, 0x30, 0x30, 0x78, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x6e, 0x66, 0x06, 0x06, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x06, 0x1c, 0x30, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x08, 0x0c, 0x0c, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x6b, 0x6b, 0x6b, 0x7f, 0x36, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x36, 0x1c, 0x1c, 0x1c, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7e, 0x60, 0x30, 0x1f, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x33, 0x18, 0x0c, 0x06, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x6e, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x36, 0x63, 0x63, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x3c, 0x66, 0x43, 0x03, 0x03, 0x03, 0x43, 0x66, 0x3c, 0x30, 0x60, 0x3e, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x30, 0x18, 0x0c, 0x00, 0x3e, 0x63, 0x7f, 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x08, 0x1c, 0x36, 0x00, 0x1e, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x33, 0x00, 0x00, 0x1e, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x06, 0x0c, 0x18, 0x00, 0x1e, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x1c, 0x36, 0x1c, 0x00, 0x1e, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x66, 0x3c, 0x30, 0x60, 0x3c, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x08, 0x1c, 0x36, 0x00, 0x3e, 0x63, 0x7f, 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x63, 0x00, 0x00, 0x3e, 0x63, 0x7f, 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x06, 0x0c, 0x18, 0x00, 0x3e, 0x63, 0x7f, 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x66, 0x00, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x18, 0x3c, 0x66, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x06, 0x0c, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x63, 0x00, 0x08, 0x1c, 0x36, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x1c, 0x36, 0x1c, 0x00, 0x1c, 0x36, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x18, 0x0c, 0x06, 0x00, 0x7f, 0x66, 0x06, 0x3e, 0x06, 0x06, 0x66, 0x7f, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x6e, 0x6c, 0x7e, 0x1b, 0x1b, 0x76, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x7c, 0x36, 0x33, 0x33, 0x7f, 0x33, 0x33, 0x33, 0x33, 0x73, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x08, 0x1c, 0x36, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x63, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x06, 0x0c, 0x18, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x0c, 0x1e, 0x33, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x06, 0x0c, 0x18, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x63, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7e, 0x60, 0x30, 0x1e, 0x00 }}, -{{ 0x00, 0x63, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x63, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x18, 0x18, 0x3c, 0x66, 0x06, 0x06, 0x06, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x1c, 0x36, 0x26, 0x06, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x67, 0x3f, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x1f, 0x33, 0x33, 0x1f, 0x23, 0x33, 0x7b, 0x33, 0x33, 0x33, 0x63, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x70, 0xd8, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00, 0x00 }}, -{{ 0x00, 0x18, 0x0c, 0x06, 0x00, 0x1e, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x30, 0x18, 0x0c, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x18, 0x0c, 0x06, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x18, 0x0c, 0x06, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x6e, 0x3b, 0x00, 0x3b, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x6e, 0x3b, 0x00, 0x63, 0x67, 0x6f, 0x7f, 0x7b, 0x73, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x3c, 0x36, 0x36, 0x7c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x1c, 0x36, 0x36, 0x1c, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x0c, 0x0c, 0x06, 0x03, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x03, 0x03, 0x43, 0x63, 0x33, 0x18, 0x0c, 0x06, 0x3b, 0x61, 0x30, 0x18, 0x7c, 0x00, 0x00 }}, -{{ 0x00, 0x03, 0x03, 0x43, 0x63, 0x33, 0x18, 0x0c, 0x66, 0x73, 0x79, 0x7c, 0x60, 0x60, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x36, 0x1b, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x36, 0x6c, 0x36, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 }}, -{{ 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }}, -{{ 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee }}, -{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }}, -{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }}, -{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }}, -{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6f, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }}, -{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6f, 0x60, 0x6f, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }}, -{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x60, 0x6f, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }}, -{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6f, 0x60, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }}, -{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }}, -{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }}, -{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }}, -{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xec, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }}, -{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xec, 0x0c, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0xec, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }}, -{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xef, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xef, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }}, -{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xec, 0x0c, 0xec, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xef, 0x00, 0xef, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }}, -{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }}, -{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }}, -{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xff, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }}, -{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }}, -{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }}, -{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }}, -{{ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f }}, -{{ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0 }}, -{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, 0x1b, 0x1b, 0x3b, 0x6e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x1e, 0x33, 0x33, 0x33, 0x1b, 0x33, 0x63, 0x63, 0x63, 0x33, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x7f, 0x63, 0x63, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x7f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x7f, 0x63, 0x06, 0x0c, 0x18, 0x0c, 0x06, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x03, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x1c, 0x36, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x1c, 0x36, 0x63, 0x63, 0x63, 0x36, 0x36, 0x36, 0x36, 0x77, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x78, 0x0c, 0x18, 0x30, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0xc0, 0x60, 0x7e, 0xdb, 0xdb, 0xcf, 0x7e, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x38, 0x0c, 0x06, 0x06, 0x3e, 0x06, 0x06, 0x06, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x70, 0xd8, 0xd8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }}, -{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x1b, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x00, 0x6e, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x1c, 0x36, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x37, 0x36, 0x36, 0x3c, 0x38, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x1b, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x0e, 0x1b, 0x0c, 0x06, 0x13, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }}, -}; diff --git a/tools/ioemu/gui/Makefile b/tools/ioemu/gui/Makefile deleted file mode 100644 index e6ddc74e06..0000000000 --- a/tools/ioemu/gui/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -TOPDIR= .. -CXXFLAGS=-I. -I../include -I.. -OBJS= gui.o keymap.o siminterface.o textconfig.o x.o rfb.o term.o - -all: libgui.a - -libgui.a: $(OBJS) - $(AR) $(ARFLAGS) $@ $(OBJS) - -include $(TOPDIR)/mk/helix.mk - -install:: all diff --git a/tools/ioemu/gui/Makefile.in b/tools/ioemu/gui/Makefile.in deleted file mode 100644 index c9fd86558a..0000000000 --- a/tools/ioemu/gui/Makefile.in +++ /dev/null @@ -1,561 +0,0 @@ -# Copyright (C) 2002 MandrakeSoft S.A. -# -# MandrakeSoft S.A. -# 43, rue d'Aboukir -# 75002 Paris - France -# http://www.linux-mandrake.com/ -# http://www.mandrakesoft.com/ -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -# Makefile for the gui component of bochs - - -@SUFFIX_LINE@ - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -srcdir = @srcdir@ -VPATH = @srcdir@ -bindir = @bindir@ -libdir = @libdir@ -mandir = @mandir@ -man1dir = $(mandir)/man1 -man5dir = $(mandir)/man5 -docdir = $(prefix)/share/doc/bochs -sharedir = $(prefix)/share/bochs -top_builddir = .. -top_srcdir = @top_srcdir@ - -SHELL = /bin/sh - -@SET_MAKE@ - -CXX = @CXX@ -CXXFLAGS = $(BX_INCDIRS) @CXXFLAGS@ @GUI_CXXFLAGS@ -LOCAL_CXXFLAGS = -LDFLAGS = @LDFLAGS@ -LIBS = @LIBS@ -X_CFLAGS = @X_CFLAGS@ -RANLIB = @RANLIB@ -PLUGIN_PATH=@libdir@ -top_builddir = .. -LIBTOOL=@LIBTOOL@ -WIN32_DLL_IMPORT_LIBRARY=../dllexports.a -BX_INCDIRS = -I.. -I$(srcdir)/.. -I../iodev -I$(srcdir)/../iodev -I../@INSTRUMENT_DIR@ -I$(srcdir)/../@INSTRUMENT_DIR@ - -GUI_OBJS_X11 = x.o -GUI_OBJS_SDL = sdl.o -GUI_OBJS_SVGA = svga.o -GUI_OBJS_BEOS = beos.o -GUI_OBJS_WIN32 = win32.o -GUI_OBJS_MACOS = macintosh.o -GUI_OBJS_CARBON = carbon.o -GUI_OBJS_NOGUI = nogui.o -GUI_OBJS_TERM = term.o -GUI_OBJS_RFB = rfb.o -GUI_OBJS_AMIGAOS = amigaos.o -GUI_OBJS_WX = wx.o -GUI_OBJS_WX_SUPPORT = wxmain.o wxdialog.o -OBJS_THAT_CANNOT_BE_PLUGINS = keymap.o gui.o siminterface.o textconfig.o @DIALOG_OBJS@ -OBJS_THAT_CAN_BE_PLUGINS = @GUI_OBJS@ - -X_LIBS = @X_LIBS@ -X_PRE_LIBS = @X_PRE_LIBS@ -GUI_LINK_OPTS_X = $(X_LIBS) $(X_PRE_LIBS) -lX11 -lXpm -GUI_LINK_OPTS_SDL = `sdl-config --cflags --libs` -GUI_LINK_OPTS_SVGA = -lvga -lvgagl -GUI_LINK_OPTS_BEOS = -lbe -GUI_LINK_OPTS_RFB = @RFB_LIBS@ -GUI_LINK_OPTS_AMIGAOS = -GUI_LINK_OPTS_WIN32 = -luser32 -lgdi32 -lcomdlg32 -lcomctl32 -GUI_LINK_OPTS_WIN32_VCPP = user32.lib gdi32.lib winmm.lib \ - comdlg32.lib comctl32.lib wsock32.lib -GUI_LINK_OPTS_MACOS = -GUI_LINK_OPTS_CARBON = -framework Carbon -GUI_LINK_OPTS_NOGUI = -GUI_LINK_OPTS_TERM = @GUI_LINK_OPTS_TERM@ -GUI_LINK_OPTS_WX = @GUI_LINK_OPTS_WX@ -GUI_LINK_OPTS = @GUI_LINK_OPTS@ @DEVICE_LINK_OPTS@ - -NONPLUGIN_OBJS = @GUI_NON_PLUGIN_OBJS@ -PLUGIN_OBJS = @GUI_PLUGIN_OBJS@ - -# -# -------- end configurable options -------------------------- -# - -all: libgui.a - -plugins: $(PLUGIN_OBJS:@PLUGIN_LIBNAME_TRANSFORMATION@) - -libgui.a: $(NONPLUGIN_OBJS) - @RMCOMMAND@ libgui.a - @MAKELIB@ $(NONPLUGIN_OBJS) - @RANLIB@ libgui.a - -# standard compile rule for C++ files -.@CPP_SUFFIX@.o: - $(CXX) @DASH@c $(CXXFLAGS) $(LOCAL_CXXFLAGS) @CXXFP@$< @OFP@$@ - -##### building plugins with libtool -%.lo: %.@CPP_SUFFIX@ - $(LIBTOOL) --mode=compile $(CXX) -c $(CXXFLAGS) $(LOCAL_CXXFLAGS) $< -o $@ - -libbx_%.la: %.lo - $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) - -libbx_x.la: x.lo - $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_X) - -libbx_sdl.la: sdl.lo - $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_SDL) - -libbx_svga.la: svga.lo - $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_SVGA) - -libbx_beos.la: beos.lo - $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_BEOS) - -libbx_rfb.la: rfb.lo - $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_RFB) - -libbx_amigaos.la: amigaos.lo - $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_AMIGAOS) - -libbx_win32.la: win32.lo - $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_WIN32) - -libbx_macos.la: macos.lo - $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_MACOS) - -libbx_carbon.la: carbon.lo - $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_CARBON) - -libbx_nogui.la: nogui.lo - $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_NOGUI) - -libbx_term.la: term.lo - $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_TERM) - -# special link rules for plugins that require more than one object file -libbx_wx.la: $(GUI_OBJS_WX:.o=.lo) $(GUI_OBJS_WX_SUPPORT:.o=.lo) - $(LIBTOOL) --mode=link $(CXX) -module $(GUI_OBJS_WX:.o=.lo) $(GUI_OBJS_WX_SUPPORT:.o=.lo) -o libbx_wx.la -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_WX) - -#### building DLLs for win32 (tested on cygwin only) -bx_%.dll: %.o - $(CXX) $(CXXFLAGS) -shared -o $@ $< $(WIN32_DLL_IMPORT_LIBRARY) $(GUI_LINK_OPTS_WIN32) - -bx_wx.dll: $(GUI_OBJS_WX) $(GUI_OBJS_WX_SUPPORT) - $(CXX) $(CXXFLAGS) -shared -o bx_wx.dll $(GUI_OBJS_WX) $(GUI_OBJS_WX_SUPPORT) $(WIN32_DLL_IMPORT_LIBRARY) `wx-config --libs` -luser32 -lgdi32 -lcomdlg32 -lcomctl32 - -bx_sdl.dll: $(GUI_OBJS_SDL) - $(CXX) $(CXXFLAGS) -shared -o bx_sdl.dll $(GUI_OBJS_SDL) $(WIN32_DLL_IMPORT_LIBRARY) $(GUI_LINK_OPTS_SDL) - -bx_rfb.dll: $(GUI_OBJS_RFB) - $(CXX) $(CXXFLAGS) -shared -o bx_rfb.dll $(GUI_OBJS_RFB) $(WIN32_DLL_IMPORT_LIBRARY) $(GUI_LINK_OPTS_RFB) - -# no need to build DLLs for beos.o -# no need to build DLLs for x.o - -##### end DLL section - -clean: - @RMCOMMAND@ -rf .libs *.la *.a *.lo *.o *.dll - -dist-clean: clean - @RMCOMMAND@ Makefile - -########################################### -# all other dependencies generated by -# gcc -MM -I.. -I../instrument/stubs `wx-config --cxxflags` *.cc | -# sed -e 's/\.cc/.@CPP_SUFFIX@/g' -# gcc -MM -I.. -I../instrument/stubs `wx-config --cxxflags` *.cc | \ -# sed -e 's/\.cc/.@CPP_SUFFIX@/g' -e 's/\.o:/.lo:/g' -# -# This means that every source file is listed twice, once with a .o rule -# and then again with an identical .lo rule. The .lo rules are used when -# building plugins. -########################################### -amigaos.o: amigaos.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ - ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \ - ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \ - ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \ - ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \ - ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \ - ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \ - ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \ - ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \ - ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \ - ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h \ - icon_bochs.h amigagui.h -beos.o: beos.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h ../font/vga.bitmap.h -carbon.o: carbon.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h icon_bochs.h ../font/vga.bitmap.h -gui.o: gui.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h ../gui/bitmaps/floppya.h \ - ../gui/bitmaps/floppyb.h ../gui/bitmaps/mouse.h \ - ../gui/bitmaps/reset.h ../gui/bitmaps/power.h \ - ../gui/bitmaps/snapshot.h ../gui/bitmaps/copy.h \ - ../gui/bitmaps/paste.h ../gui/bitmaps/configbutton.h \ - ../gui/bitmaps/cdromd.h ../gui/bitmaps/userbutton.h -keymap.o: keymap.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h -macintosh.o: macintosh.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ - ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \ - ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \ - ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \ - ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \ - ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \ - ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \ - ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \ - ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \ - ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \ - ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h \ - icon_bochs.h ../font/vga.bitmap.h -nogui.o: nogui.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h icon_bochs.h -rfb.o: rfb.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h icon_bochs.h ../font/vga.bitmap.h \ - rfbproto.h -sdl.o: sdl.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h icon_bochs.h sdl.h sdlkeys.h -siminterface.o: siminterface.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ - ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \ - ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \ - ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \ - ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \ - ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \ - ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \ - ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \ - ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \ - ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \ - ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h -svga.o: svga.@CPP_SUFFIX@ ../font/vga.bitmap.h ../bochs.h ../config.h ../osdep.h \ - ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \ - ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \ - ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \ - ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \ - ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \ - ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \ - ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \ - ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \ - ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \ - ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h \ - icon_bochs.h -term.o: term.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h icon_bochs.h -textconfig.o: textconfig.@CPP_SUFFIX@ ../config.h ../osdep.h textconfig.h \ - siminterface.h ../extplugin.h ../ltdl.h -win32.o: win32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h icon_bochs.h ../font/vga.bitmap.h -wx.o: wx.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h ../gui/icon_bochs.h \ - ../font/vga.bitmap.h wxmain.h -wxdialog.o: wxdialog.@CPP_SUFFIX@ ../config.h ../osdep.h ../gui/siminterface.h \ - ../bxversion.h wxdialog.h wxmain.h -wxmain.o: wxmain.@CPP_SUFFIX@ ../config.h ../osdep.h ../gui/siminterface.h \ - ../bxversion.h wxdialog.h wxmain.h ../extplugin.h ../ltdl.h \ - bitmaps/cdromd.xpm bitmaps/copy.xpm bitmaps/floppya.xpm \ - bitmaps/floppyb.xpm bitmaps/paste.xpm bitmaps/power.xpm \ - bitmaps/reset.xpm bitmaps/snapshot.xpm bitmaps/mouse.xpm \ - bitmaps/userbutton.xpm -x.o: x.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h icon_bochs.h -amigaos.lo: amigaos.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ - ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \ - ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \ - ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \ - ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \ - ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \ - ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \ - ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \ - ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \ - ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \ - ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h \ - icon_bochs.h amigagui.h -beos.lo: beos.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h ../font/vga.bitmap.h -carbon.lo: carbon.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h icon_bochs.h ../font/vga.bitmap.h -gui.lo: gui.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h ../gui/bitmaps/floppya.h \ - ../gui/bitmaps/floppyb.h ../gui/bitmaps/mouse.h \ - ../gui/bitmaps/reset.h ../gui/bitmaps/power.h \ - ../gui/bitmaps/snapshot.h ../gui/bitmaps/copy.h \ - ../gui/bitmaps/paste.h ../gui/bitmaps/configbutton.h \ - ../gui/bitmaps/cdromd.h ../gui/bitmaps/userbutton.h -keymap.lo: keymap.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h -macintosh.lo: macintosh.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ - ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \ - ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \ - ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \ - ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \ - ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \ - ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \ - ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \ - ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \ - ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \ - ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h \ - icon_bochs.h ../font/vga.bitmap.h -nogui.lo: nogui.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h icon_bochs.h -rfb.lo: rfb.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h icon_bochs.h ../font/vga.bitmap.h \ - rfbproto.h -sdl.lo: sdl.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h icon_bochs.h sdl.h sdlkeys.h -siminterface.lo: siminterface.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ - ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \ - ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \ - ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \ - ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \ - ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \ - ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \ - ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \ - ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \ - ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \ - ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h -svga.lo: svga.@CPP_SUFFIX@ ../font/vga.bitmap.h ../bochs.h ../config.h ../osdep.h \ - ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \ - ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \ - ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \ - ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \ - ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \ - ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \ - ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \ - ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \ - ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \ - ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h \ - icon_bochs.h -term.lo: term.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h icon_bochs.h -textconfig.lo: textconfig.@CPP_SUFFIX@ ../config.h ../osdep.h textconfig.h \ - siminterface.h ../extplugin.h ../ltdl.h -win32.lo: win32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h icon_bochs.h ../font/vga.bitmap.h -wx.lo: wx.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h ../gui/icon_bochs.h \ - ../font/vga.bitmap.h wxdialog.h wxmain.h -wxdialog.lo: wxdialog.@CPP_SUFFIX@ ../config.h ../osdep.h ../gui/siminterface.h \ - ../bxversion.h wxdialog.h wxmain.h -wxmain.lo: wxmain.@CPP_SUFFIX@ ../config.h ../osdep.h ../gui/siminterface.h \ - ../bxversion.h wxdialog.h wxmain.h ../extplugin.h ../ltdl.h \ - bitmaps/cdromd.xpm bitmaps/copy.xpm bitmaps/floppya.xpm \ - bitmaps/floppyb.xpm bitmaps/paste.xpm bitmaps/power.xpm \ - bitmaps/reset.xpm bitmaps/snapshot.xpm bitmaps/mouse.xpm \ - bitmaps/userbutton.xpm -x.lo: x.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ - ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \ - ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \ - ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ - ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \ - ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \ - ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \ - ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \ - ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \ - ../iodev/guest2host.h ../iodev/slowdown_timer.h \ - ../instrument/stubs/instrument.h icon_bochs.h diff --git a/tools/ioemu/gui/bitmaps/cdromd.h b/tools/ioemu/gui/bitmaps/cdromd.h deleted file mode 100644 index 49d78e122c..0000000000 --- a/tools/ioemu/gui/bitmaps/cdromd.h +++ /dev/null @@ -1,34 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: cdromd.h,v 1.1 2002/01/31 21:16:52 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -#define BX_CDROMD_BMAP_X 32 -#define BX_CDROMD_BMAP_Y 32 - -static const unsigned char bx_cdromd_bmap[(BX_CONFIG_BMAP_X * BX_CONFIG_BMAP_Y)/8] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x0e, 0x00, 0x00, 0x10, 0x12, 0x00, - 0x00, 0x10, 0x12, 0x00, 0x00, 0x10, 0x12, 0x00, 0x00, 0x60, 0x0e, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x0c, 0x30, 0x00, - 0x00, 0xe2, 0x47, 0x00, 0x00, 0x19, 0x98, 0x00, 0x80, 0xe6, 0x67, 0x01, - 0x40, 0x19, 0x98, 0x02, 0x20, 0xe5, 0xa7, 0x04, 0xa0, 0x12, 0x48, 0x05, - 0x90, 0xca, 0x53, 0x09, 0x50, 0x25, 0xa4, 0x0a, 0x50, 0x15, 0xa8, 0x0a, - 0x50, 0x15, 0xa8, 0x0a, 0x50, 0x15, 0xa8, 0x0a, 0x50, 0x15, 0xa8, 0x0a, - 0x50, 0x25, 0xa4, 0x0a, 0x90, 0xca, 0x53, 0x09, 0xa0, 0x12, 0x48, 0x05, - 0x20, 0xe5, 0xa7, 0x04, 0x40, 0x19, 0x98, 0x02, 0x80, 0xe6, 0x67, 0x01, - 0x00, 0x19, 0x98, 0x00, 0x00, 0xe2, 0x47, 0x00, 0x00, 0x0c, 0x30, 0x00, - 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - -static const unsigned char bx_cdromd_eject_bmap[(BX_CONFIG_BMAP_X * BX_CONFIG_BMAP_Y)/8] = { - 0x01, 0x00, 0x00, 0x80, 0x02, 0x60, 0x0e, 0x40, 0x04, 0x10, 0x12, 0x20, - 0x08, 0x10, 0x12, 0x10, 0x10, 0x10, 0x12, 0x08, 0x20, 0x60, 0x0e, 0x04, - 0x40, 0x00, 0x00, 0x02, 0x80, 0xf0, 0x0f, 0x01, 0x00, 0x0d, 0xb0, 0x00, - 0x00, 0xe2, 0x47, 0x00, 0x00, 0x1d, 0xb8, 0x00, 0x80, 0xee, 0x77, 0x01, - 0x40, 0x19, 0x98, 0x02, 0x20, 0xe5, 0xa7, 0x04, 0xa0, 0x52, 0x4a, 0x05, - 0x90, 0xca, 0x53, 0x09, 0x50, 0xa5, 0xa5, 0x0a, 0x50, 0x55, 0xaa, 0x0a, - 0x50, 0x35, 0xac, 0x0a, 0x50, 0x15, 0xa8, 0x0a, 0x50, 0x1d, 0xb8, 0x0a, - 0x50, 0x25, 0xa4, 0x0a, 0x90, 0xca, 0x53, 0x09, 0xa0, 0x13, 0xc8, 0x05, - 0xa0, 0xe5, 0xa7, 0x05, 0x40, 0x19, 0x98, 0x02, 0xa0, 0xe6, 0x67, 0x05, - 0x10, 0x19, 0x98, 0x08, 0x08, 0xe2, 0x47, 0x10, 0x04, 0x0c, 0x30, 0x20, - 0x02, 0xf0, 0x0f, 0x40, 0x01, 0x00, 0x00, 0x80 - }; diff --git a/tools/ioemu/gui/bitmaps/cdromd.xpm b/tools/ioemu/gui/bitmaps/cdromd.xpm deleted file mode 100644 index 7a216b0bfe..0000000000 --- a/tools/ioemu/gui/bitmaps/cdromd.xpm +++ /dev/null @@ -1,41 +0,0 @@ -/* XPM */ -static char *cdromd_xpm[] = { -/* width height num_colors chars_per_pixel */ -" 32 32 2 1", -/* colors */ -". c None", -"# c #000000", -/* pixels */ -"................................", -".............##..###............", -"............#....#..#...........", -"............#....#..#...........", -"............#....#..#...........", -".............##..###............", -"................................", -"............########............", -"..........##........##..........", -".........#...######...#.........", -"........#..##......##..#........", -".......#.##..######..##.#.......", -"......#.#..##......##..#.#......", -".....#..#.#..######..#.#..#.....", -".....#.#.#..#......#..#.#.#.....", -"....#..#.#.#..####..#.#.#..#....", -"....#.#.#.#..#....#..#.#.#.#....", -"....#.#.#.#.#......#.#.#.#.#....", -"....#.#.#.#.#......#.#.#.#.#....", -"....#.#.#.#.#......#.#.#.#.#....", -"....#.#.#.#.#......#.#.#.#.#....", -"....#.#.#.#..#....#..#.#.#.#....", -"....#..#.#.#..####..#.#.#..#....", -".....#.#.#..#......#..#.#.#.....", -".....#..#.#..######..#.#..#.....", -"......#.#..##......##..#.#......", -".......#.##..######..##.#.......", -"........#..##......##..#........", -".........#...######...#.........", -"..........##........##..........", -"............########............", -"................................" -}; diff --git a/tools/ioemu/gui/bitmaps/configbutton.h b/tools/ioemu/gui/bitmaps/configbutton.h deleted file mode 100644 index 7c51ff9b69..0000000000 --- a/tools/ioemu/gui/bitmaps/configbutton.h +++ /dev/null @@ -1,16 +0,0 @@ -#define BX_CONFIG_BMAP_X 32 -#define BX_CONFIG_BMAP_Y 32 - -static const unsigned char bx_config_bmap[(BX_CONFIG_BMAP_X * BX_CONFIG_BMAP_Y)/8] = { - 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80, 0x01, 0xfc, 0x7f, 0xc0, 0x03, - 0xfc, 0xff, 0xc1, 0x03, 0xfc, 0xff, 0xc1, 0x03, 0xfc, 0x7f, 0xc0, 0x03, - 0x84, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03, - 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03, - 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03, - 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03, - 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xe0, 0x07, 0x80, 0x07, 0xf0, 0x0f, - 0x80, 0x07, 0x70, 0x0e, 0x80, 0x07, 0x30, 0x0c, 0x80, 0x07, 0x30, 0x0c, - 0x80, 0x07, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x38, 0x27, 0xba, 0x1c, - 0x84, 0x68, 0x8a, 0x02, 0x84, 0xa8, 0xba, 0x32, 0x84, 0x28, 0x8b, 0x22, - 0x38, 0x27, 0x8a, 0x1c, 0x00, 0x00, 0x00, 0x00 - }; diff --git a/tools/ioemu/gui/bitmaps/configbutton.xpm b/tools/ioemu/gui/bitmaps/configbutton.xpm deleted file mode 100644 index ef2f933828..0000000000 --- a/tools/ioemu/gui/bitmaps/configbutton.xpm +++ /dev/null @@ -1,41 +0,0 @@ -/* XPM */ -static char *configbutton_xpm[] = { -/* width height num_colors chars_per_pixel */ -" 32 32 2 1", -/* colors */ -". c None", -"# c #000000", -/* pixels */ -"................................", -"..#....................##.......", -"..#############.......####......", -"..###############.....####......", -"..###############.....####......", -"..#############.......####......", -"..#....####...........####......", -".......####...........####......", -".......####...........####......", -".......####...........####......", -".......####...........####......", -".......####...........####......", -".......####...........####......", -".......####...........####......", -".......####...........####......", -".......####...........####......", -".......####...........####......", -".......####...........####......", -".......####...........####......", -".......####..........######.....", -".......####.........########....", -".......####.........###..###....", -".......####.........##....##....", -".......####.........##....##....", -".......####..........#....#.....", -"................................", -"...###..###..#...#.###.#..###...", -"..#....#...#.##..#.#...#.#......", -"..#....#...#.#.#.#.###.#.#..##..", -"..#....#...#.#..##.#...#.#...#..", -"...###..###..#...#.#...#..###...", -"................................" -}; diff --git a/tools/ioemu/gui/bitmaps/copy.h b/tools/ioemu/gui/bitmaps/copy.h deleted file mode 100644 index 78546c979f..0000000000 --- a/tools/ioemu/gui/bitmaps/copy.h +++ /dev/null @@ -1,18 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: copy.h,v 1.1 2002/03/11 15:04:58 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -#define BX_COPY_BMAP_X 32 -#define BX_COPY_BMAP_Y 32 - -static unsigned char bx_copy_bmap[(BX_COPY_BMAP_X*BX_COPY_BMAP_Y)] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, - 0x80, 0x60, 0x4e, 0x02, 0x80, 0x90, 0x52, 0x02, 0x80, 0x90, 0x52, 0x02, - 0x00, 0x6f, 0x8e, 0x03, 0x00, 0x00, 0x02, 0x02, 0xf8, 0x3f, 0x02, 0x02, - 0x08, 0x20, 0xc0, 0x01, 0xe8, 0x2b, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, - 0xe8, 0x2e, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0xe8, 0x39, 0x00, 0x00, - 0x08, 0x24, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0xe8, 0xaf, 0xff, 0x03, - 0x08, 0xa0, 0x00, 0x02, 0xf8, 0xbf, 0xbe, 0x02, 0x00, 0x80, 0x00, 0x02, - 0x80, 0x88, 0xee, 0x02, 0x80, 0x90, 0x00, 0x02, 0x00, 0xbf, 0x9e, 0x03, - 0x00, 0x90, 0x40, 0x02, 0x00, 0x88, 0x08, 0x02, 0x00, 0x80, 0xfe, 0x02, - 0x00, 0x80, 0x00, 0x02, 0x00, 0x80, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; diff --git a/tools/ioemu/gui/bitmaps/copy.xpm b/tools/ioemu/gui/bitmaps/copy.xpm deleted file mode 100644 index 5e0138e87a..0000000000 --- a/tools/ioemu/gui/bitmaps/copy.xpm +++ /dev/null @@ -1,41 +0,0 @@ -/* XPM */ -static char *copy_xpm[] = { -/* width height num_colors chars_per_pixel */ -" 32 32 2 1", -/* colors */ -". c None", -"# c #000000", -/* pixels */ -"................................", -"........####....................", -".......#........................", -".......#.....##..###..#..#......", -".......#....#..#.#..#.#..#......", -".......#....#..#.#..#.#..#......", -"........####.##..###...###......", -".................#.......#......", -"...###########...#.......#......", -"...#.........#........###.......", -"...#.#####.#.#..................", -"...#.........#..................", -"...#.###.###.#..................", -"...#.........#..................", -"...#.####..###..................", -"...#......#..#..................", -"...#...#.....#..................", -"...#.#######.#.###########......", -"...#.........#.#.........#......", -"...###########.#.#####.#.#......", -"...............#.........#......", -".......#...#...#.###.###.#......", -".......#....#..#.........#......", -"........######.#.####..###......", -"............#..#......#..#......", -"...........#...#...#.....#......", -"...............#.#######.#......", -"...............#.........#......", -"...............###########......", -"................................", -"................................", -"................................" -}; diff --git a/tools/ioemu/gui/bitmaps/floppya.h b/tools/ioemu/gui/bitmaps/floppya.h deleted file mode 100644 index 86ba90f6f6..0000000000 --- a/tools/ioemu/gui/bitmaps/floppya.h +++ /dev/null @@ -1,34 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: floppya.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -#define BX_FLOPPYA_BMAP_X 32 -#define BX_FLOPPYA_BMAP_Y 32 - -static const unsigned char bx_floppya_bmap[(BX_FLOPPYA_BMAP_X * BX_FLOPPYA_BMAP_Y)/8] = { - 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x40, 0x11, 0x00, - 0x00, 0xc0, 0x01, 0x00, 0x00, 0x60, 0x13, 0x00, 0x00, 0x60, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0x01, 0x80, 0x07, - 0x20, 0xfd, 0xbf, 0x04, 0x20, 0x01, 0x80, 0x04, 0xe0, 0xfd, 0xbf, 0x07, - 0xe0, 0x01, 0x80, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x01, 0x80, 0x07, - 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x01, 0x80, 0x07, 0xe0, 0xfd, 0xbf, 0x07, - 0xe0, 0x01, 0x80, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x01, 0x80, 0x07, - 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, - 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xaf, 0xea, 0x07, 0xe0, 0xf7, 0xd5, 0x07, - 0xe0, 0xef, 0xea, 0x07, 0xe0, 0xf7, 0xd5, 0x07, 0xc0, 0xef, 0xea, 0x07, - 0x80, 0x57, 0xd5, 0x07, 0x00, 0xaf, 0xea, 0x07 - }; - -static const unsigned char bx_floppya_eject_bmap[(BX_FLOPPYA_BMAP_X * BX_FLOPPYA_BMAP_Y)/8] = { - 0x01, 0x80, 0x00, 0x80, 0x02, 0x40, 0x01, 0x40, 0x04, 0x40, 0x11, 0x20, - 0x08, 0xc0, 0x01, 0x10, 0x10, 0x60, 0x13, 0x08, 0x20, 0x60, 0x03, 0x04, - 0x40, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0x01, 0x80, 0x07, - 0x20, 0xff, 0xff, 0x04, 0x20, 0x05, 0xa0, 0x04, 0xe0, 0xfd, 0xbf, 0x07, - 0xe0, 0x11, 0x88, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x41, 0x82, 0x07, - 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x81, 0x81, 0x07, 0xe0, 0xfd, 0xbf, 0x07, - 0xe0, 0x21, 0x84, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x09, 0x90, 0x07, - 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, - 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xaf, 0xea, 0x07, 0xe0, 0xf7, 0xd5, 0x07, - 0xf0, 0xef, 0xea, 0x0f, 0xe8, 0xf7, 0xd5, 0x17, 0xc4, 0xef, 0xea, 0x27, - 0x82, 0x57, 0xd5, 0x47, 0x01, 0xaf, 0xea, 0x87 - }; diff --git a/tools/ioemu/gui/bitmaps/floppya.xpm b/tools/ioemu/gui/bitmaps/floppya.xpm deleted file mode 100644 index 637f198b9b..0000000000 --- a/tools/ioemu/gui/bitmaps/floppya.xpm +++ /dev/null @@ -1,41 +0,0 @@ -/* XPM */ -static char *floppya_xpm[] = { -/* width height num_colors chars_per_pixel */ -" 32 32 2 1", -/* colors */ -". c None", -"# c #000000", -/* pixels */ -"...............#................", -"..............#.#...............", -"..............#.#...#...........", -"..............###...............", -".............##.##..#...........", -".............##.##..............", -"................................", -".....######################.....", -".....####..............####.....", -".....#..#.############.#..#.....", -".....#..#..............#..#.....", -".....####.############.####.....", -".....####..............####.....", -".....####.############.####.....", -".....####..............####.....", -".....####.############.####.....", -".....####..............####.....", -".....####.############.####.....", -".....####..............####.....", -".....####.############.####.....", -".....####..............####.....", -".....######################.....", -".....######################.....", -".....######################.....", -".....######################.....", -".....#######.#.#.#.#.######.....", -".....######.#####.#.#.#####.....", -".....#######.###.#.#.######.....", -".....######.#####.#.#.#####.....", -"......######.###.#.#.######.....", -".......####.#.#.#.#.#.#####.....", -"........####.#.#.#.#.######....." -}; diff --git a/tools/ioemu/gui/bitmaps/floppyb.h b/tools/ioemu/gui/bitmaps/floppyb.h deleted file mode 100644 index 70c7597201..0000000000 --- a/tools/ioemu/gui/bitmaps/floppyb.h +++ /dev/null @@ -1,34 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: floppyb.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -#define BX_FLOPPYB_BMAP_X 32 -#define BX_FLOPPYB_BMAP_Y 32 - -static const unsigned char bx_floppyb_bmap[(BX_FLOPPYB_BMAP_X * BX_FLOPPYB_BMAP_Y)/8] = { - 0x00, 0xe0, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0xe0, 0x08, 0x00, - 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x09, 0x00, 0x00, 0xe0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0x01, 0x80, 0x07, - 0x20, 0xfd, 0xbf, 0x04, 0x20, 0x01, 0x80, 0x04, 0xe0, 0xfd, 0xbf, 0x07, - 0xe0, 0x01, 0x80, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x01, 0x80, 0x07, - 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x01, 0x80, 0x07, 0xe0, 0xfd, 0xbf, 0x07, - 0xe0, 0x01, 0x80, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x01, 0x80, 0x07, - 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, - 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xaf, 0xea, 0x07, 0xe0, 0xf7, 0xd5, 0x07, - 0xe0, 0xef, 0xea, 0x07, 0xe0, 0xf7, 0xd5, 0x07, 0xc0, 0xef, 0xea, 0x07, - 0x80, 0x57, 0xd5, 0x07, 0x00, 0xaf, 0xea, 0x07 - }; - -static const unsigned char bx_floppyb_eject_bmap[(BX_FLOPPYB_BMAP_X * BX_FLOPPYB_BMAP_Y)/8] = { - 0x01, 0xe0, 0x00, 0x80, 0x02, 0x20, 0x01, 0x40, 0x04, 0xe0, 0x08, 0x20, - 0x08, 0x20, 0x01, 0x10, 0x10, 0x20, 0x09, 0x08, 0x20, 0xe0, 0x00, 0x04, - 0x40, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0x01, 0x80, 0x07, - 0x20, 0xff, 0xff, 0x04, 0x20, 0x05, 0xa0, 0x04, 0xe0, 0xfd, 0xbf, 0x07, - 0xe0, 0x11, 0x88, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x41, 0x82, 0x07, - 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x81, 0x81, 0x07, 0xe0, 0xfd, 0xbf, 0x07, - 0xe0, 0x21, 0x84, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x09, 0x90, 0x07, - 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, - 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xaf, 0xea, 0x07, 0xe0, 0xf7, 0xd5, 0x07, - 0xf0, 0xef, 0xea, 0x0f, 0xe8, 0xf7, 0xd5, 0x17, 0xc4, 0xef, 0xea, 0x27, - 0x82, 0x57, 0xd5, 0x47, 0x01, 0xaf, 0xea, 0x87 - }; diff --git a/tools/ioemu/gui/bitmaps/floppyb.xpm b/tools/ioemu/gui/bitmaps/floppyb.xpm deleted file mode 100644 index f4e20e5dcb..0000000000 --- a/tools/ioemu/gui/bitmaps/floppyb.xpm +++ /dev/null @@ -1,41 +0,0 @@ -/* XPM */ -static char *floppyb_xpm[] = { -/* width height num_colors chars_per_pixel */ -" 32 32 2 1", -/* colors */ -". c None", -"# c #000000", -/* pixels */ -".............###................", -".............#..#...............", -".............###...#............", -".............#..#...............", -".............#..#..#............", -".............###................", -"................................", -".....######################.....", -".....####..............####.....", -".....#..#.############.#..#.....", -".....#..#..............#..#.....", -".....####.############.####.....", -".....####..............####.....", -".....####.############.####.....", -".....####..............####.....", -".....####.############.####.....", -".....####..............####.....", -".....####.############.####.....", -".....####..............####.....", -".....####.############.####.....", -".....####..............####.....", -".....######################.....", -".....######################.....", -".....######################.....", -".....######################.....", -".....#######.#.#.#.#.######.....", -".....######.#####.#.#.#####.....", -".....#######.###.#.#.######.....", -".....######.#####.#.#.#####.....", -"......######.###.#.#.######.....", -".......####.#.#.#.#.#.#####.....", -"........####.#.#.#.#.######....." -}; diff --git a/tools/ioemu/gui/bitmaps/mouse.h b/tools/ioemu/gui/bitmaps/mouse.h deleted file mode 100644 index cc8f364125..0000000000 --- a/tools/ioemu/gui/bitmaps/mouse.h +++ /dev/null @@ -1,34 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: mouse.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -#define BX_MOUSE_BMAP_X 32 -#define BX_MOUSE_BMAP_Y 32 - -static unsigned char bx_mouse_bmap[(BX_MOUSE_BMAP_X * BX_MOUSE_BMAP_Y)/8] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xf8, 0x1f, 0x00, - 0x00, 0x0c, 0x30, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x06, 0x40, 0x00, - 0xf8, 0xff, 0xc0, 0x00, 0x0c, 0x80, 0xc1, 0x00, 0x24, 0x22, 0xc1, 0x00, - 0x74, 0x77, 0x81, 0x00, 0x74, 0x77, 0x81, 0x01, 0x74, 0x77, 0x81, 0x01, - 0x74, 0x77, 0x01, 0x01, 0x74, 0x77, 0x01, 0x03, 0x74, 0x77, 0x01, 0x06, - 0x24, 0x22, 0x01, 0x0c, 0x0c, 0x80, 0x01, 0x38, 0x04, 0x00, 0x01, 0x00, - 0x0c, 0x80, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x0c, 0x80, 0x01, 0x00, - 0x04, 0x00, 0x01, 0x00, 0x0c, 0x80, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, - 0x0c, 0x80, 0x01, 0x00, 0x14, 0x40, 0x01, 0x00, 0x2c, 0xa0, 0x01, 0x00, - 0x54, 0x55, 0x01, 0x00, 0xac, 0xaa, 0x01, 0x00, 0xf8, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - -static unsigned char bx_nomouse_bmap[(BX_MOUSE_BMAP_X * BX_MOUSE_BMAP_Y)/8] = { - 0x01, 0x00, 0x00, 0x80, 0x02, 0xe0, 0x07, 0x40, 0x04, 0xf8, 0x1f, 0x20, - 0x08, 0x0c, 0x30, 0x10, 0x10, 0x06, 0x60, 0x08, 0x20, 0x06, 0x40, 0x04, - 0xf8, 0xff, 0xc0, 0x02, 0x8c, 0x80, 0xc1, 0x01, 0x24, 0x23, 0xc1, 0x00, - 0x74, 0x77, 0xc1, 0x00, 0x74, 0x77, 0xa1, 0x01, 0x74, 0x7f, 0x91, 0x01, - 0x74, 0x77, 0x09, 0x01, 0x74, 0x77, 0x05, 0x03, 0x74, 0x77, 0x03, 0x06, - 0x24, 0xa2, 0x01, 0x0c, 0x0c, 0x80, 0x01, 0x38, 0x04, 0x40, 0x03, 0x00, - 0x0c, 0xa0, 0x05, 0x00, 0x04, 0x10, 0x09, 0x00, 0x0c, 0x88, 0x11, 0x00, - 0x04, 0x04, 0x21, 0x00, 0x0c, 0x82, 0x41, 0x00, 0x04, 0x01, 0x81, 0x00, - 0x8c, 0x80, 0x01, 0x01, 0x54, 0x40, 0x01, 0x02, 0x2c, 0xa0, 0x01, 0x04, - 0x54, 0x55, 0x01, 0x08, 0xac, 0xaa, 0x01, 0x10, 0xfc, 0xff, 0x00, 0x20, - 0x02, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x80 - }; diff --git a/tools/ioemu/gui/bitmaps/mouse.xpm b/tools/ioemu/gui/bitmaps/mouse.xpm deleted file mode 100644 index dea33275a2..0000000000 --- a/tools/ioemu/gui/bitmaps/mouse.xpm +++ /dev/null @@ -1,41 +0,0 @@ -/* XPM */ -static char *mouse_xpm[] = { -/* width height num_colors chars_per_pixel */ -" 32 32 2 1", -/* colors */ -". c None", -"# c #000000", -/* pixels */ -"................................", -".............######.............", -"...........##########...........", -"..........##........##..........", -".........##..........##.........", -".........##...........#.........", -"...#############......##........", -"..##...........##.....##........", -"..#..#...#...#..#.....##........", -"..#.###.###.###.#......#........", -"..#.###.###.###.#......##.......", -"..#.###.###.###.#......##.......", -"..#.###.###.###.#.......#.......", -"..#.###.###.###.#.......##......", -"..#.###.###.###.#........##.....", -"..#..#...#...#..#.........##....", -"..##...........##..........###..", -"..#.............#...............", -"..##...........##...............", -"..#.............#...............", -"..##...........##...............", -"..#.............#...............", -"..##...........##...............", -"..#.............#...............", -"..##...........##...............", -"..#.#.........#.#...............", -"..##.#.......#.##...............", -"..#.#.#.#.#.#.#.#...............", -"..##.#.#.#.#.#.##...............", -"...#############................", -"................................", -"................................" -}; diff --git a/tools/ioemu/gui/bitmaps/paste.h b/tools/ioemu/gui/bitmaps/paste.h deleted file mode 100644 index f574dad3dc..0000000000 --- a/tools/ioemu/gui/bitmaps/paste.h +++ /dev/null @@ -1,18 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: paste.h,v 1.1 2002/03/11 15:04:58 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -#define BX_PASTE_BMAP_X 32 -#define BX_PASTE_BMAP_Y 32 - -static unsigned char bx_paste_bmap[(BX_PASTE_BMAP_X*BX_PASTE_BMAP_Y)] = { - 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x10, 0x00, 0x20, 0x9a, 0x93, 0x03, - 0x20, 0x66, 0x78, 0x04, 0xe0, 0xa5, 0xd3, 0x07, 0x20, 0x24, 0x54, 0x00, - 0x20, 0xd8, 0x93, 0x03, 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x02, 0x00, - 0x00, 0x7c, 0x3f, 0x00, 0xc0, 0x83, 0xc1, 0x03, 0x20, 0x02, 0x40, 0x04, - 0x20, 0x01, 0x80, 0x04, 0x20, 0x01, 0x80, 0x04, 0xa0, 0xff, 0xff, 0x05, - 0x20, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x04, 0x20, 0xf8, 0x3f, 0x04, - 0x20, 0x08, 0x20, 0x04, 0x20, 0xe8, 0x2b, 0x04, 0x20, 0x08, 0x20, 0x04, - 0x20, 0xe8, 0x2e, 0x04, 0x20, 0x08, 0x20, 0x04, 0x20, 0xe8, 0x39, 0x04, - 0x20, 0x08, 0x24, 0x04, 0x20, 0x88, 0x20, 0x04, 0x20, 0xe8, 0x2f, 0x04, - 0x20, 0x08, 0x20, 0x04, 0x20, 0xf8, 0x3f, 0x04, 0x20, 0x00, 0x00, 0x04, - 0xc0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, }; diff --git a/tools/ioemu/gui/bitmaps/paste.xpm b/tools/ioemu/gui/bitmaps/paste.xpm deleted file mode 100644 index 5c83b01dc7..0000000000 --- a/tools/ioemu/gui/bitmaps/paste.xpm +++ /dev/null @@ -1,41 +0,0 @@ -/* XPM */ -static char *paste_xpm[] = { -/* width height num_colors chars_per_pixel */ -" 32 32 2 1", -/* colors */ -". c None", -"# c #000000", -/* pixels */ -"................................", -".....####...........#...........", -".....#...#.##..###..#..###......", -".....#...##..##....####...#.....", -".....####.#..#.###..#.#####.....", -".....#....#..#....#.#.#.........", -".....#.....##.####..#..###......", -"...............##...............", -"..............##.#..............", -"..........#####.######..........", -"......####.....##.....####......", -".....#...#............#...#.....", -".....#..#..............#..#.....", -".....#..#..............#..#.....", -".....#.##################.#.....", -".....#....................#.....", -".....#....................#.....", -".....#.....###########....#.....", -".....#.....#.........#....#.....", -".....#.....#.#####.#.#....#.....", -".....#.....#.........#....#.....", -".....#.....#.###.###.#....#.....", -".....#.....#.........#....#.....", -".....#.....#.####..###....#.....", -".....#.....#......#..#....#.....", -".....#.....#...#.....#....#.....", -".....#.....#.#######.#....#.....", -".....#.....#.........#....#.....", -".....#.....###########....#.....", -".....#....................#.....", -"......####################......", -"................................" -}; diff --git a/tools/ioemu/gui/bitmaps/power.h b/tools/ioemu/gui/bitmaps/power.h deleted file mode 100644 index ba72d6a31b..0000000000 --- a/tools/ioemu/gui/bitmaps/power.h +++ /dev/null @@ -1,20 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: power.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -#define BX_POWER_BMAP_X 32 -#define BX_POWER_BMAP_Y 32 - -static const unsigned char bx_power_bmap[(BX_POWER_BMAP_X * BX_POWER_BMAP_Y)/8] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, - 0x24, 0x67, 0x66, 0x34, 0xa4, 0x28, 0x92, 0x48, 0x9a, 0xa8, 0xfa, 0x04, - 0x82, 0x64, 0x09, 0x04, 0x07, 0xa3, 0x70, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xf8, 0x03, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x0f, 0x1e, 0x00, - 0x80, 0x03, 0x38, 0x00, 0xc0, 0x00, 0x60, 0x00, 0xe0, 0xe0, 0xe0, 0x00, - 0x60, 0xe0, 0xc0, 0x00, 0x70, 0xe0, 0xc0, 0x01, 0x30, 0xe0, 0x80, 0x01, - 0x30, 0xe0, 0x80, 0x01, 0x30, 0xe0, 0x80, 0x01, 0x30, 0xe0, 0x80, 0x01, - 0x30, 0xe0, 0x80, 0x01, 0x70, 0xe0, 0xc0, 0x01, 0x60, 0xe0, 0xc0, 0x00, - 0xe0, 0xe0, 0xe0, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x80, 0x03, 0x38, 0x00, - 0x00, 0x0f, 0x1e, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0xf8, 0x03, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; diff --git a/tools/ioemu/gui/bitmaps/power.xpm b/tools/ioemu/gui/bitmaps/power.xpm deleted file mode 100644 index ff7e9e8367..0000000000 --- a/tools/ioemu/gui/bitmaps/power.xpm +++ /dev/null @@ -1,41 +0,0 @@ -/* XPM */ -static char *power_xpm[] = { -/* width height num_colors chars_per_pixel */ -" 32 32 2 1", -/* colors */ -". c None", -"# c #000000", -/* pixels */ -"................................", -"................................", -".####...........................", -"..#..#..###..##..##..##...#.##..", -"..#..#.#...#.#...#..#..#...#..#.", -".#.##..#...#.#.#.#.#####..#.....", -".#.....#..#..##.#..#......#.....", -"###.....##...#.#....###..###....", -"................................", -"...........#######..............", -".........###########............", -"........####.....####...........", -".......###.........###..........", -"......##.............##.........", -".....###.....###.....###........", -".....##......###......##........", -"....###......###......###.......", -"....##.......###.......##.......", -"....##.......###.......##.......", -"....##.......###.......##.......", -"....##.......###.......##.......", -"....##.......###.......##.......", -"....###......###......###.......", -".....##......###......##........", -".....###.....###.....###........", -"......##.............##.........", -".......###.........###..........", -"........####.....####...........", -".........###########............", -"...........#######..............", -"................................", -"................................" -}; diff --git a/tools/ioemu/gui/bitmaps/reset.h b/tools/ioemu/gui/bitmaps/reset.h deleted file mode 100644 index 046f80aeb8..0000000000 --- a/tools/ioemu/gui/bitmaps/reset.h +++ /dev/null @@ -1,20 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: reset.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -#define BX_RESET_BMAP_X 32 -#define BX_RESET_BMAP_Y 32 - -static const unsigned char bx_reset_bmap[(BX_RESET_BMAP_X * BX_RESET_BMAP_Y)/8] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3c, 0x00, 0x00, 0x10, - 0x48, 0x0c, 0xc7, 0x7c, 0x48, 0x92, 0x20, 0x11, 0x34, 0x1f, 0xf3, 0x09, - 0x24, 0x41, 0x12, 0x48, 0x6e, 0xce, 0xe1, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, - 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0xe0, 0x3f, 0x00, - 0x00, 0xc7, 0x38, 0x00, 0x00, 0x87, 0x38, 0x00, 0x00, 0x07, 0x38, 0x00, - 0x00, 0x07, 0x38, 0x00, 0x00, 0x07, 0x38, 0x00, 0x00, 0x07, 0x38, 0x00, - 0x00, 0x07, 0x38, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0xfe, 0x1f, 0x00, - 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; diff --git a/tools/ioemu/gui/bitmaps/reset.xpm b/tools/ioemu/gui/bitmaps/reset.xpm deleted file mode 100644 index d47ea6cbfd..0000000000 --- a/tools/ioemu/gui/bitmaps/reset.xpm +++ /dev/null @@ -1,41 +0,0 @@ -/* XPM */ -static char *reset_xpm[] = { -/* width height num_colors chars_per_pixel */ -" 32 32 2 1", -/* colors */ -". c None", -"# c #000000", -/* pixels */ -"................................", -".............................#..", -"..####......................#...", -"...#..#...##....###...##..#####.", -"...#..#..#..#..#.....#..#...#...", -"..#.##..#####...##..#####..#....", -"..#..#..#.....#..#..#......#..#.", -".###.##..###..###....###....##..", -"................................", -"................................", -"................................", -"................................", -"................................", -"...............#................", -"..............##................", -".............#######............", -"............#########...........", -".............#########..........", -"........###...##...###..........", -"........###....#...###..........", -"........###........###..........", -"........###........###..........", -"........###........###..........", -"........###........###..........", -"........###........###..........", -"........##############..........", -".........############...........", -"..........##########............", -"................................", -"................................", -"................................", -"................................" -}; diff --git a/tools/ioemu/gui/bitmaps/snapshot.h b/tools/ioemu/gui/bitmaps/snapshot.h deleted file mode 100644 index cced8ff9e7..0000000000 --- a/tools/ioemu/gui/bitmaps/snapshot.h +++ /dev/null @@ -1,20 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: snapshot.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -#define BX_SNAPSHOT_BMAP_X 32 -#define BX_SNAPSHOT_BMAP_Y 32 - -static const unsigned char bx_snapshot_bmap[(BX_SNAPSHOT_BMAP_X * BX_SNAPSHOT_BMAP_Y)/8] = { - 0x00, 0x00, 0x20, 0x40, 0x77, 0xe6, 0xee, 0xec, 0x91, 0xa8, 0xa2, 0x52, - 0x96, 0xac, 0xac, 0x52, 0x94, 0xaa, 0xa8, 0x52, 0xb7, 0xee, 0xae, 0xcc, - 0x00, 0x20, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x08, 0x10, 0x00, - 0x7c, 0x0f, 0x10, 0x1f, 0xfa, 0x07, 0xa0, 0x2e, 0x42, 0x07, 0xa0, 0x50, - 0xa3, 0x03, 0xc0, 0xe0, 0xff, 0xee, 0x77, 0xbf, 0x01, 0xf9, 0x9f, 0x40, - 0x01, 0x1d, 0xb8, 0xa0, 0xff, 0xe5, 0xa7, 0xff, 0xff, 0xba, 0x5a, 0xff, - 0xff, 0x55, 0xb5, 0xff, 0xff, 0x8d, 0xaa, 0xff, 0xff, 0x16, 0x55, 0xff, - 0xff, 0xa2, 0x6a, 0xff, 0xff, 0x46, 0x55, 0xff, 0xff, 0xaa, 0x6a, 0xff, - 0xff, 0x56, 0x55, 0xff, 0xfe, 0xae, 0x6a, 0x7f, 0x00, 0x55, 0xb5, 0x00, - 0x00, 0xbd, 0xba, 0x00, 0x00, 0xfa, 0x5f, 0x00, 0x00, 0xe4, 0x27, 0x00, - 0x00, 0x18, 0x18, 0x00, 0x00, 0xe0, 0x07, 0x00 - }; diff --git a/tools/ioemu/gui/bitmaps/snapshot.xpm b/tools/ioemu/gui/bitmaps/snapshot.xpm deleted file mode 100644 index c17305beb5..0000000000 --- a/tools/ioemu/gui/bitmaps/snapshot.xpm +++ /dev/null @@ -1,41 +0,0 @@ -/* XPM */ -static char *snapshot_xpm[] = { -/* width height num_colors chars_per_pixel */ -" 32 32 2 1", -/* colors */ -". c None", -"# c #000000", -/* pixels */ -".....................#........#.", -"###.###..##..###.###.###..##.###", -"#...#..#...#.#.#.#...#.#.#..#.#.", -".##.#..#..##.#.#..##.#.#.#..#.#.", -"..#.#..#.#.#.#.#...#.#.#.#..#.#.", -"###.##.#.###.###.###.#.#..##..##", -".............#..................", -"............########............", -"...........#........#...........", -"..#####.####........#...#####...", -".#.########..........#.#.###.#..", -".#....#.###..........#.#....#.#.", -"##...#.###............##.....###", -"########.###.######.###.######.#", -"#.......#..##########..#......#.", -"#.......#.###......###.#.....#.#", -"#########.#..######..#.#########", -"########.#.###.#.#.##.#.########", -"#########.#.#.#.#.#.##.#########", -"#########.##...#.#.#.#.#########", -"########.##.#...#.#.#.#.########", -"########.#...#.#.#.#.##.########", -"########.##...#.#.#.#.#.########", -"########.#.#.#.#.#.#.##.########", -"########.##.#.#.#.#.#.#.########", -".#######.###.#.#.#.#.##.#######.", -"........#.#.#.#.#.#.##.#........", -"........#.####.#.#.###.#........", -".........#.##########.#.........", -"..........#..######..#..........", -"...........##......##...........", -".............######............." -}; diff --git a/tools/ioemu/gui/bitmaps/userbutton.h b/tools/ioemu/gui/bitmaps/userbutton.h deleted file mode 100644 index c93f50664b..0000000000 --- a/tools/ioemu/gui/bitmaps/userbutton.h +++ /dev/null @@ -1,19 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: userbutton.h,v 1.1 2002/08/09 06:16:43 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -#define BX_USER_BMAP_X 32 -#define BX_USER_BMAP_Y 32 - -static const unsigned char bx_user_bmap[BX_USER_BMAP_X*BX_USER_BMAP_Y/8] = { - 0x00, 0x00, 0x00, 0x00, 0x84, 0x78, 0x9e, 0x07, 0x84, 0x04, 0x82, 0x08, - 0x84, 0x04, 0x82, 0x08, 0x84, 0x38, 0x9e, 0x07, 0x84, 0x40, 0x82, 0x01, - 0x84, 0x40, 0x82, 0x06, 0x78, 0x3c, 0x9e, 0x08, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1c, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, - 0x00, 0x00, 0x80, 0x00, 0xfe, 0xff, 0xff, 0x3f, 0x02, 0x00, 0x00, 0x20, - 0xaa, 0xaa, 0x2a, 0x2a, 0x02, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x20, - 0xaa, 0xaa, 0xaa, 0x2a, 0x52, 0x55, 0x11, 0x25, 0xaa, 0xaa, 0xaa, 0x2a, - 0x52, 0x55, 0x01, 0x25, 0xaa, 0xaa, 0x82, 0x2a, 0x52, 0x55, 0x11, 0x25, - 0xaa, 0xbf, 0xaa, 0x2a, 0x02, 0x00, 0x00, 0x20, 0xfe, 0xff, 0xff, 0x3f, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; diff --git a/tools/ioemu/gui/bitmaps/userbutton.xpm b/tools/ioemu/gui/bitmaps/userbutton.xpm deleted file mode 100644 index a5d1f99eec..0000000000 --- a/tools/ioemu/gui/bitmaps/userbutton.xpm +++ /dev/null @@ -1,40 +0,0 @@ -/* XPM */ -static char *userbutton_xpm[] = { -/* columns rows colors chars-per-pixel */ -"32 32 2 1", -". c None", -"# c #000000", -/* pixels */ -"................................", -"..#....#...####..####..####.....", -"..#....#..#......#.....#...#....", -"..#....#..#......#.....#...#....", -"..#....#...###...####..####.....", -"..#....#......#..#.....##.......", -"..#....#......#..#.....#.##.....", -"...####...####...####..#...#....", -"................................", -"................................", -".............................#..", -"..........................###...", -".........................#......", -"........................#.......", -".......................#........", -".......................#........", -".#############################..", -".#...........................#..", -".#.#.#.#.#.#.#.#.#.#.#...#.#.#..", -".#...........................#..", -".#...........................#..", -".#.#.#.#.#.#.#.#.#.#.#.#.#.#.#..", -".#..#.#.#.#.#.#.#...#...#.#..#..", -".#.#.#.#.#.#.#.#.#.#.#.#.#.#.#..", -".#..#.#.#.#.#.#.#.......#.#..#..", -".#.#.#.#.#.#.#.#.#.....#.#.#.#..", -".#..#.#.#.#.#.#.#...#...#.#..#..", -".#.#.#.#######.#.#.#.#.#.#.#.#..", -".#...........................#..", -".#############################..", -"................................", -"................................" -}; diff --git a/tools/ioemu/gui/gui.cc b/tools/ioemu/gui/gui.cc deleted file mode 100644 index d3c2383d1e..0000000000 --- a/tools/ioemu/gui/gui.cc +++ /dev/null @@ -1,601 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: gui.cc,v 1.73 2003/12/18 20:04:48 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -#include -#include "bochs.h" -#include "gui/bitmaps/floppya.h" -#include "gui/bitmaps/floppyb.h" -#include "gui/bitmaps/mouse.h" -#include "gui/bitmaps/reset.h" -#include "gui/bitmaps/power.h" -#include "gui/bitmaps/snapshot.h" -#include "gui/bitmaps/copy.h" -#include "gui/bitmaps/paste.h" -#include "gui/bitmaps/configbutton.h" -#include "gui/bitmaps/cdromd.h" -#include "gui/bitmaps/userbutton.h" -#if BX_WITH_MACOS -# include -#endif - -bx_gui_c *bx_gui = NULL; - -#define BX_GUI_THIS bx_gui-> -#define LOG_THIS BX_GUI_THIS - -bx_gui_c::bx_gui_c(void) -{ - put("GUI"); // Init in specific_init - settype(GUILOG); -} - -bx_gui_c::~bx_gui_c() -{ -} - - void -bx_gui_c::init(int argc, char **argv, unsigned tilewidth, unsigned tileheight) -{ - specific_init(argc, argv, tilewidth, tileheight, BX_HEADER_BAR_Y); - - // Define some bitmaps to use in the headerbar - BX_GUI_THIS floppyA_bmap_id = create_bitmap(bx_floppya_bmap, - BX_FLOPPYA_BMAP_X, BX_FLOPPYA_BMAP_Y); - BX_GUI_THIS floppyA_eject_bmap_id = create_bitmap(bx_floppya_eject_bmap, - BX_FLOPPYA_BMAP_X, BX_FLOPPYA_BMAP_Y); - BX_GUI_THIS floppyB_bmap_id = create_bitmap(bx_floppyb_bmap, - BX_FLOPPYB_BMAP_X, BX_FLOPPYB_BMAP_Y); - BX_GUI_THIS floppyB_eject_bmap_id = create_bitmap(bx_floppyb_eject_bmap, - BX_FLOPPYB_BMAP_X, BX_FLOPPYB_BMAP_Y); - BX_GUI_THIS cdromD_bmap_id = create_bitmap(bx_cdromd_bmap, - BX_CDROMD_BMAP_X, BX_CDROMD_BMAP_Y); - BX_GUI_THIS cdromD_eject_bmap_id = create_bitmap(bx_cdromd_eject_bmap, - BX_CDROMD_BMAP_X, BX_CDROMD_BMAP_Y); - BX_GUI_THIS mouse_bmap_id = create_bitmap(bx_mouse_bmap, - BX_MOUSE_BMAP_X, BX_MOUSE_BMAP_Y); - BX_GUI_THIS nomouse_bmap_id = create_bitmap(bx_nomouse_bmap, - BX_MOUSE_BMAP_X, BX_MOUSE_BMAP_Y); - - - BX_GUI_THIS power_bmap_id = create_bitmap(bx_power_bmap, BX_POWER_BMAP_X, BX_POWER_BMAP_Y); - BX_GUI_THIS reset_bmap_id = create_bitmap(bx_reset_bmap, BX_RESET_BMAP_X, BX_RESET_BMAP_Y); - BX_GUI_THIS snapshot_bmap_id = create_bitmap(bx_snapshot_bmap, BX_SNAPSHOT_BMAP_X, BX_SNAPSHOT_BMAP_Y); - BX_GUI_THIS copy_bmap_id = create_bitmap(bx_copy_bmap, BX_COPY_BMAP_X, BX_COPY_BMAP_Y); - BX_GUI_THIS paste_bmap_id = create_bitmap(bx_paste_bmap, BX_PASTE_BMAP_X, BX_PASTE_BMAP_Y); - BX_GUI_THIS config_bmap_id = create_bitmap(bx_config_bmap, BX_CONFIG_BMAP_X, BX_CONFIG_BMAP_Y); - BX_GUI_THIS user_bmap_id = create_bitmap(bx_user_bmap, BX_USER_BMAP_X, BX_USER_BMAP_Y); - - - // Add the initial bitmaps to the headerbar, and enable callback routine, for use - // when that bitmap is clicked on - - // Floppy A: - BX_GUI_THIS floppyA_status = DEV_floppy_get_media_status(0); - if (BX_GUI_THIS floppyA_status) - BX_GUI_THIS floppyA_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyA_bmap_id, - BX_GRAVITY_LEFT, floppyA_handler); - else - BX_GUI_THIS floppyA_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyA_eject_bmap_id, - BX_GRAVITY_LEFT, floppyA_handler); - - // Floppy B: - BX_GUI_THIS floppyB_status = DEV_floppy_get_media_status(1); - if (BX_GUI_THIS floppyB_status) - BX_GUI_THIS floppyB_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyB_bmap_id, - BX_GRAVITY_LEFT, floppyB_handler); - else - BX_GUI_THIS floppyB_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyB_eject_bmap_id, - BX_GRAVITY_LEFT, floppyB_handler); - - // CDROM, - // valgrinds says that the harddrive object is not be initialised yet, - // so we just set the bitmap to ejected for now -#if 0 - if (DEV_hd_present()) { - Bit32u handle = DEV_hd_get_first_cd_handle(); - BX_GUI_THIS cdromD_status = DEV_hd_get_cd_media_status(handle); - } - - if (BX_GUI_THIS cdromD_status) - BX_GUI_THIS cdromD_hbar_id = headerbar_bitmap(BX_GUI_THIS cdromD_bmap_id, - BX_GRAVITY_LEFT, cdromD_handler); - else -#endif - BX_GUI_THIS cdromD_hbar_id = headerbar_bitmap(BX_GUI_THIS cdromD_eject_bmap_id, - BX_GRAVITY_LEFT, cdromD_handler); - - // Mouse button - if (bx_options.Omouse_enabled->get ()) - BX_GUI_THIS mouse_hbar_id = headerbar_bitmap(BX_GUI_THIS mouse_bmap_id, - BX_GRAVITY_LEFT, toggle_mouse_enable); - else - BX_GUI_THIS mouse_hbar_id = headerbar_bitmap(BX_GUI_THIS nomouse_bmap_id, - BX_GRAVITY_LEFT, toggle_mouse_enable); - - // These are the buttons on the right side. They are created in order - // of right to left. - - // Power button - BX_GUI_THIS power_hbar_id = headerbar_bitmap(BX_GUI_THIS power_bmap_id, - BX_GRAVITY_RIGHT, power_handler); - // Reset button - BX_GUI_THIS reset_hbar_id = headerbar_bitmap(BX_GUI_THIS reset_bmap_id, - BX_GRAVITY_RIGHT, reset_handler); - // Configure button - BX_GUI_THIS config_hbar_id = headerbar_bitmap(BX_GUI_THIS config_bmap_id, - BX_GRAVITY_RIGHT, config_handler); - // Snapshot button - BX_GUI_THIS snapshot_hbar_id = headerbar_bitmap(BX_GUI_THIS snapshot_bmap_id, - BX_GRAVITY_RIGHT, snapshot_handler); - // Paste button - BX_GUI_THIS paste_hbar_id = headerbar_bitmap(BX_GUI_THIS paste_bmap_id, - BX_GRAVITY_RIGHT, paste_handler); - // Copy button - BX_GUI_THIS copy_hbar_id = headerbar_bitmap(BX_GUI_THIS copy_bmap_id, - BX_GRAVITY_RIGHT, copy_handler); - // User button - BX_GUI_THIS user_hbar_id = headerbar_bitmap(BX_GUI_THIS user_bmap_id, - BX_GRAVITY_RIGHT, userbutton_handler); - - if(bx_options.Otext_snapshot_check->get()) { - bx_pc_system.register_timer(this, bx_gui_c::snapshot_checker, (unsigned) 1000000, 1, 1, "snap_chk"); - } - - BX_GUI_THIS charmap_updated = 0; - - show_headerbar(); -} - -void -bx_gui_c::update_drive_status_buttons (void) { - BX_GUI_THIS floppyA_status = - DEV_floppy_get_media_status(0) - && bx_options.floppya.Ostatus->get (); - BX_GUI_THIS floppyB_status = - DEV_floppy_get_media_status(1) - && bx_options.floppyb.Ostatus->get (); - Bit32u handle = DEV_hd_get_first_cd_handle(); - BX_GUI_THIS cdromD_status = DEV_hd_get_cd_media_status(handle); - if (BX_GUI_THIS floppyA_status) - replace_bitmap(BX_GUI_THIS floppyA_hbar_id, BX_GUI_THIS floppyA_bmap_id); - else { -#if BX_WITH_MACOS - // If we are using the Mac floppy driver, eject the disk - // from the floppy drive. This doesn't work in MacOS X. - if (!strcmp(bx_options.floppya.Opath->getptr (), SuperDrive)) - DiskEject(1); -#endif - replace_bitmap(BX_GUI_THIS floppyA_hbar_id, BX_GUI_THIS floppyA_eject_bmap_id); - } - if (BX_GUI_THIS floppyB_status) - replace_bitmap(BX_GUI_THIS floppyB_hbar_id, BX_GUI_THIS floppyB_bmap_id); - else { -#if BX_WITH_MACOS - // If we are using the Mac floppy driver, eject the disk - // from the floppy drive. This doesn't work in MacOS X. - if (!strcmp(bx_options.floppyb.Opath->getptr (), SuperDrive)) - DiskEject(1); -#endif - replace_bitmap(BX_GUI_THIS floppyB_hbar_id, BX_GUI_THIS floppyB_eject_bmap_id); - } - if (BX_GUI_THIS cdromD_status) - replace_bitmap(BX_GUI_THIS cdromD_hbar_id, BX_GUI_THIS cdromD_bmap_id); - else { - replace_bitmap(BX_GUI_THIS cdromD_hbar_id, BX_GUI_THIS cdromD_eject_bmap_id); - } -} - - void -bx_gui_c::floppyA_handler(void) -{ - if (bx_options.floppya.Odevtype->get() == BX_FLOPPY_NONE) - return; // no primary floppy device present -#ifdef WIN32 - if (strcmp(bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get()), - "rfb")) { - // instead of just toggling the status, call win32dialog to bring up - // a dialog asking what disk image you want to switch to. - int ret = SIM->ask_param (BXP_FLOPPYA_PATH); - if (ret > 0) { - BX_GUI_THIS update_drive_status_buttons (); - } - return; - } -#endif - BX_GUI_THIS floppyA_status = !BX_GUI_THIS floppyA_status; - DEV_floppy_set_media_status(0, BX_GUI_THIS floppyA_status); - BX_GUI_THIS update_drive_status_buttons (); -} - - void -bx_gui_c::floppyB_handler(void) -{ - if (bx_options.floppyb.Odevtype->get() == BX_FLOPPY_NONE) - return; // no secondary floppy device present -#ifdef WIN32 - if (strcmp(bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get()), - "rfb")) { - // instead of just toggling the status, call win32dialog to bring up - // a dialog asking what disk image you want to switch to. - int ret = SIM->ask_param (BXP_FLOPPYB_PATH); - if (ret > 0) { - BX_GUI_THIS update_drive_status_buttons (); - } - return; - } -#endif - BX_GUI_THIS floppyB_status = !BX_GUI_THIS floppyB_status; - DEV_floppy_set_media_status(1, BX_GUI_THIS floppyB_status); - BX_GUI_THIS update_drive_status_buttons (); -} - - void -bx_gui_c::cdromD_handler(void) -{ - Bit32u handle = DEV_hd_get_first_cd_handle(); - if (!strcmp(bx_options.Osel_config->get_choice(bx_options.Osel_config->get()), - "wx")) { - // instead of just toggling the status, call wxWindows to bring up - // a dialog asking what disk image you want to switch to. - // BBD: for now, find the first cdrom and call ask_param on that. - // Since we could have multiple cdroms now, maybe we should be adding - // one cdrom button for each? - bx_param_c *cdrom = SIM->get_first_cdrom (); - if (cdrom == NULL) - return; // no cdrom found - int ret = SIM->ask_param (cdrom->get_id ()); - if (ret < 0) return; // cancelled - // eject and then insert the disk. If the new path is invalid, - // the status will return 0. - unsigned status = DEV_hd_set_cd_media_status(handle, 0); - printf ("eject disk, new_status is %d\n", status); - status = DEV_hd_set_cd_media_status(handle, 1); - printf ("insert disk, new_status is %d\n", status); - fflush (stdout); - BX_GUI_THIS cdromD_status = status; - } else { - BX_GUI_THIS cdromD_status = - DEV_hd_set_cd_media_status(handle, !BX_GUI_THIS cdromD_status); - } - BX_GUI_THIS update_drive_status_buttons (); -} - - void -bx_gui_c::reset_handler(void) -{ - BX_INFO(( "system RESET callback." )); - bx_pc_system.ResetSignal( PCS_SET ); /* XXX is this right? */ - for (int i=0; ireset(BX_RESET_HARDWARE); -} - -#ifdef BX_USE_VMX -char xm_destroy[PATH_MAX]; -#endif - - void -bx_gui_c::power_handler(void) -{ - // the user pressed power button, so there's no doubt they want bochs - // to quit. Change panics to fatal for the GUI and then do a panic. - bx_user_quit = 1; - LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL); - BX_INFO(("POWER button turned off.")); - // shouldn't reach this point, but if you do, QUIT!!! - fprintf (stderr, "Bochs is exiting because you pressed the power button.\n"); - snprintf(xm_destroy, PATH_MAX, "xm destroy %d", domid); - BX_INFO(("executing: %s\n", xm_destroy)); - if (system(xm_destroy) != 0) { - BX_PANIC(("failed\n")); - } - BX_EXIT (1); -} - -Bit32s -bx_gui_c::make_text_snapshot (char **snapshot, Bit32u *length) -{ - Bit8u* raw_snap = NULL; - char *clean_snap; - unsigned line_addr, txt_addr, txHeight, txWidth; - - DEV_vga_get_text_snapshot(&raw_snap, &txHeight, &txWidth); - if (txHeight <= 0) return -1; - clean_snap = (char*) malloc(txHeight*(txWidth+2)+1); - txt_addr = 0; - for (unsigned i=0; i 0) && (clean_snap[txt_addr-1] == ' ')) txt_addr--; -#ifdef WIN32 - if(!(bx_options.Otext_snapshot_check->get())) { - clean_snap[txt_addr++] = 13; - } -#endif - clean_snap[txt_addr++] = 10; - } - clean_snap[txt_addr] = 0; - *snapshot = clean_snap; - *length = txt_addr; - return 0; -} - -// create a text snapshot and copy to the system clipboard. On guis that -// we haven't figured out how to support yet, dump to a file instead. - void -bx_gui_c::copy_handler(void) -{ - Bit32u len; - char *text_snapshot; - if (make_text_snapshot (&text_snapshot, &len) < 0) { - BX_INFO(( "copy button failed, mode not implemented")); - return; - } - if (!BX_GUI_THIS set_clipboard_text(text_snapshot, len)) { - // platform specific code failed, use portable code instead - FILE *fp = fopen("copy.txt", "w"); - fwrite(text_snapshot, 1, len, fp); - fclose(fp); - } - free(text_snapshot); -} - -// Check the current text snapshot against file snapchk.txt. - void -bx_gui_c::snapshot_checker(void * this_ptr) -{ - char filename[BX_PATHNAME_LEN]; - strcpy(filename,"snapchk.txt"); - FILE *fp = fopen(filename, "rb"); - if(fp) { - char *text_snapshot; - Bit32u len; - if (make_text_snapshot (&text_snapshot, &len) < 0) { - return; - } - char *compare_snapshot = (char *) malloc((len+1) * sizeof(char)); - fread(compare_snapshot, 1, len, fp); - fclose(fp); - strcpy(filename,"snapmask.txt"); - fp=fopen(filename, "rb"); - if(fp) { - char *mask_snapshot = (char *) malloc((len+1) * sizeof(char)); - unsigned i; - bx_bool flag = 1; - fread(mask_snapshot, 1, len, fp); - fclose(fp); - for(i=0;iget_choice(bx_options.Osel_displaylib->get()), - "rfb")) { -#else - if (!strcmp(bx_options.Osel_config->get_choice(bx_options.Osel_config->get()), - "wx")) { -#endif - int ret = SIM->ask_filename (filename, sizeof(filename), - "Save snapshot as...", "snapshot.txt", - bx_param_string_c::SAVE_FILE_DIALOG); - if (ret < 0) { // cancelled - free(text_snapshot); - return; - } - } else { - strcpy (filename, "snapshot.txt"); - } - FILE *fp = fopen(filename, "wb"); - fwrite(text_snapshot, 1, len, fp); - fclose(fp); - free(text_snapshot); -} - -// Read ASCII chars from the system clipboard and paste them into bochs. -// Note that paste cannot work with the key mapping tables loaded. - void -bx_gui_c::paste_handler(void) -{ - Bit32s nbytes; - Bit8u *bytes; - if (!bx_keymap.isKeymapLoaded ()) { - BX_ERROR (("keyboard_mapping disabled, so paste cannot work")); - return; - } - if (!BX_GUI_THIS get_clipboard_text(&bytes, &nbytes)) { - BX_ERROR (("paste not implemented on this platform")); - return; - } - BX_INFO (("pasting %d bytes", nbytes)); - DEV_kbd_paste_bytes (bytes, nbytes); -} - - - void -bx_gui_c::config_handler(void) -{ - if (strcmp(bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get()), - "rfb")) { - SIM->configuration_interface (NULL, CI_RUNTIME_CONFIG); - } -} - - void -bx_gui_c::toggle_mouse_enable(void) -{ - int old = bx_options.Omouse_enabled->get (); - BX_DEBUG (("toggle mouse_enabled, now %d", !old)); - bx_options.Omouse_enabled->set (!old); -} - - void -bx_gui_c::userbutton_handler(void) -{ - unsigned shortcut[4]; - unsigned p; - char *user_shortcut; - int i, len, ret = 1; - - len = 0; -#ifdef WIN32 - if (strcmp(bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get()), - "rfb")) { -#else - if (!strcmp(bx_options.Osel_config->get_choice(bx_options.Osel_config->get()), - "wx")) { -#endif - ret = SIM->ask_param (BXP_USER_SHORTCUT); - } - user_shortcut = bx_options.Ouser_shortcut->getptr(); - if ((ret > 0) && user_shortcut[0] && (strcmp(user_shortcut, "none"))) { - len = 0; - p = 0; - while ((p < strlen(user_shortcut)) && (len < 3)) { - if (!strncmp(user_shortcut+p, "alt", 3)) { - shortcut[len++] = BX_KEY_ALT_L; - p += 3; - } else if (!strncmp(user_shortcut+p, "ctrl", 4)) { - shortcut[len++] = BX_KEY_CTRL_L; - p += 4; - } else if (!strncmp(user_shortcut+p, "del", 3)) { - shortcut[len++] = BX_KEY_DELETE; - p += 3; - } else if (!strncmp(user_shortcut+p, "esc", 3)) { - shortcut[len++] = BX_KEY_ESC; - p += 3; - } else if (!strncmp(user_shortcut+p, "f1", 2)) { - shortcut[len++] = BX_KEY_F1; - p += 2; - } else if (!strncmp(user_shortcut+p, "f4", 2)) { - shortcut[len++] = BX_KEY_F4; - p += 2; - } else if (!strncmp(user_shortcut+p, "tab", 3)) { - shortcut[len++] = BX_KEY_TAB; - p += 3; - } else if (!strncmp(user_shortcut+p, "win", 3)) { - shortcut[len++] = BX_KEY_WIN_L; - p += 3; - } else if (!strncmp(user_shortcut+p, "bksp", 4)) { - shortcut[len++] = BX_KEY_BACKSPACE; - p += 4; - } else { - BX_ERROR(("Unknown shortcut %s ignored", user_shortcut)); - return; - } - } - i = 0; - while (i < len) { - DEV_kbd_gen_scancode(shortcut[i++]); - } - i--; - while (i >= 0) { - DEV_kbd_gen_scancode(shortcut[i--] | BX_KEY_RELEASED); - } - } -} - - void -bx_gui_c::mouse_enabled_changed (bx_bool val) -{ - // This is only called when SIM->get_init_done is 1. Note that VAL - // is the new value of mouse_enabled, which may not match the old - // value which is still in bx_options.Omouse_enabled->get (). - BX_DEBUG (("replacing the mouse bitmaps")); - if (val) - BX_GUI_THIS replace_bitmap(BX_GUI_THIS mouse_hbar_id, BX_GUI_THIS mouse_bmap_id); - else - BX_GUI_THIS replace_bitmap(BX_GUI_THIS mouse_hbar_id, BX_GUI_THIS nomouse_bmap_id); - // give the GUI a chance to respond to the event. Most guis will hide - // the native mouse cursor and do something to trap the mouse inside the - // bochs VGA display window. - BX_GUI_THIS mouse_enabled_changed_specific (val); -} - -void -bx_gui_c::init_signal_handlers () -{ -#if BX_GUI_SIGHANDLER - if (bx_gui_sighandler) - { - Bit32u mask = bx_gui->get_sighandler_mask (); - for (Bit32u sig=0; sig<32; sig++) - { - if (mask & (1<> 5] = 1; - BX_GUI_THIS charmap_updated = 1; -} diff --git a/tools/ioemu/gui/gui.h b/tools/ioemu/gui/gui.h deleted file mode 100644 index 14a44caa71..0000000000 --- a/tools/ioemu/gui/gui.h +++ /dev/null @@ -1,352 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: gui.h,v 1.40 2003/06/28 08:04:31 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -typedef struct { - Bit8u cs_start; - Bit8u cs_end; - Bit16u line_offset; - Bit16u line_compare; - Bit8u h_panning; - Bit8u v_panning; - bx_bool line_graphics; -} bx_vga_tminfo_t; - - -BOCHSAPI extern class bx_gui_c *bx_gui; - - -// The bx_gui_c class provides data and behavior that is common to -// all guis. Each gui implementation will override the abstract methods. -class BOCHSAPI bx_gui_c : public logfunctions { -public: - bx_gui_c (void); - virtual ~bx_gui_c (); - // Define the following functions in the module for your particular GUI - // (x.cc, beos.cc, ...) - virtual void specific_init(int argc, char **argv, - unsigned x_tilesize, unsigned y_tilesize, unsigned header_bar_y) = 0; - virtual void text_update(Bit8u *old_text, Bit8u *new_text, - unsigned long cursor_x, unsigned long cursor_y, - bx_vga_tminfo_t tm_info, unsigned rows) = 0; - virtual void graphics_tile_update(Bit8u *snapshot, unsigned x, unsigned y) = 0; - virtual void handle_events(void) = 0; - virtual void flush(void) = 0; - virtual void clear_screen(void) = 0; - virtual bx_bool palette_change(unsigned index, unsigned red, unsigned green, unsigned blue) = 0; - virtual void dimension_update(unsigned x, unsigned y, unsigned fheight=0, unsigned fwidth=0, unsigned bpp=8) = 0; - virtual unsigned create_bitmap(const unsigned char *bmap, unsigned xdim, unsigned ydim) = 0; - virtual unsigned headerbar_bitmap(unsigned bmap_id, unsigned alignment, void (*f)(void)) = 0; - virtual void replace_bitmap(unsigned hbar_id, unsigned bmap_id) = 0; - virtual void show_headerbar(void) = 0; - virtual int get_clipboard_text(Bit8u **bytes, Bit32s *nbytes) = 0; - virtual int set_clipboard_text(char *snapshot, Bit32u len) = 0; - virtual void mouse_enabled_changed_specific (bx_bool val) = 0; - virtual void exit(void) = 0; - // set_display_mode() changes the mode between the configuration interface - // and the simulation. This is primarily intended for display libraries - // which have a full-screen mode such as SDL, term, and svgalib. The display - // mode is set to DISP_MODE_CONFIG before displaying any configuration menus, - // for panics that requires user input, when entering the debugger, etc. It - // is set to DISP_MODE_SIM when the Bochs simulation resumes. The - // enum is defined in gui/siminterface.h. - virtual void set_display_mode (disp_mode_t newmode) { /* default=no action*/ } - // These are only needed for the term gui. For all other guis they will - // have no effect. - // returns 32-bit bitmask in which 1 means the GUI should handle that signal - virtual Bit32u get_sighandler_mask () {return 0;} - // called when registered signal arrives - virtual void sighandler (int sig) {} -#if BX_USE_IDLE_HACK - // this is called from the CPU model when the HLT instruction is executed. - virtual void sim_is_idle(void) {} -#endif - - // The following function(s) are defined already, and your - // GUI code calls them - static void key_event(Bit32u key); - static void set_text_charmap(Bit8u *fbuffer); - static void set_text_charbyte(Bit16u address, Bit8u data); - - void init(int argc, char **argv, - unsigned x_tilesize, unsigned y_tilesize); - void update_drive_status_buttons (void); - static void mouse_enabled_changed (bx_bool val); - static void init_signal_handlers (); - - -protected: - // And these are defined and used privately in gui.cc - static void floppyA_handler(void); - static void floppyB_handler(void); - static void cdromD_handler(void); - static void reset_handler(void); - static void power_handler(void); - static void copy_handler(void); - static void paste_handler(void); - static void snapshot_handler(void); - static void snapshot_checker(void *); - static void config_handler(void); - static void toggle_mouse_enable(void); - static void userbutton_handler(void); - static Bit32s make_text_snapshot (char **snapshot, Bit32u *length); - - bx_bool floppyA_status; - bx_bool floppyB_status; - bx_bool cdromD_status; - unsigned floppyA_bmap_id, floppyA_eject_bmap_id, floppyA_hbar_id; - unsigned floppyB_bmap_id, floppyB_eject_bmap_id, floppyB_hbar_id; - unsigned cdromD_bmap_id, cdromD_eject_bmap_id, cdromD_hbar_id; - unsigned power_bmap_id, power_hbar_id; - unsigned reset_bmap_id, reset_hbar_id; - unsigned copy_bmap_id, copy_hbar_id; - unsigned paste_bmap_id, paste_hbar_id; - unsigned snapshot_bmap_id, snapshot_hbar_id; - unsigned config_bmap_id, config_hbar_id; - unsigned mouse_bmap_id, nomouse_bmap_id, mouse_hbar_id; - unsigned user_bmap_id, user_hbar_id; - - unsigned char vga_charmap[0x2000]; - bx_bool charmap_updated; - bx_bool char_changed[256]; - disp_mode_t disp_mode; - }; - - -// Add this macro in the class declaration of each GUI, to define all the -// required virtual methods. Example: -// -// class bx_rfb_gui_c : public bx_gui_c { -// public: -// bx_rfb_gui_c (void) {} -// DECLARE_GUI_VIRTUAL_METHODS() -// }; -// Then, each method must be defined later in the file. -#define DECLARE_GUI_VIRTUAL_METHODS() \ - virtual void specific_init(int argc, char **argv, \ - unsigned x_tilesize, unsigned y_tilesize, \ - unsigned header_bar_y); \ - virtual void text_update(Bit8u *old_text, Bit8u *new_text, \ - unsigned long cursor_x, unsigned long cursor_y, \ - bx_vga_tminfo_t tm_info, unsigned rows); \ - virtual void graphics_tile_update(Bit8u *snapshot, unsigned x, unsigned y); \ - virtual void handle_events(void); \ - virtual void flush(void); \ - virtual void clear_screen(void); \ - virtual bx_bool palette_change(unsigned index, \ - unsigned red, unsigned green, unsigned blue); \ - virtual void dimension_update(unsigned x, unsigned y, unsigned fheight=0, \ - unsigned fwidth=0, unsigned bpp=8); \ - virtual unsigned create_bitmap(const unsigned char *bmap, \ - unsigned xdim, unsigned ydim); \ - virtual unsigned headerbar_bitmap(unsigned bmap_id, unsigned alignment, \ - void (*f)(void)); \ - virtual void replace_bitmap(unsigned hbar_id, unsigned bmap_id); \ - virtual void show_headerbar(void); \ - virtual int get_clipboard_text(Bit8u **bytes, Bit32s *nbytes); \ - virtual int set_clipboard_text(char *snapshot, Bit32u len); \ - virtual void mouse_enabled_changed_specific (bx_bool val); \ - virtual void exit(void); \ - /* end of DECLARE_GUI_VIRTUAL_METHODS */ - -#define BX_MAX_PIXMAPS 16 -#define BX_MAX_HEADERBAR_ENTRIES 11 -#define BX_HEADER_BAR_Y 32 - -// align pixmaps towards left or right side of header bar -#define BX_GRAVITY_LEFT 10 -#define BX_GRAVITY_RIGHT 11 - -#define BX_KEY_PRESSED 0x00000000 -#define BX_KEY_RELEASED 0x80000000 - -#define BX_KEY_UNHANDLED 0x10000000 - -#define BX_KEY_CTRL_L 0 -#define BX_KEY_SHIFT_L 1 - -#define BX_KEY_F1 2 -#define BX_KEY_F2 3 -#define BX_KEY_F3 4 -#define BX_KEY_F4 5 -#define BX_KEY_F5 6 -#define BX_KEY_F6 7 -#define BX_KEY_F7 8 -#define BX_KEY_F8 9 -#define BX_KEY_F9 10 -#define BX_KEY_F10 11 -#define BX_KEY_F11 12 -#define BX_KEY_F12 13 - -#define BX_KEY_CTRL_R 14 -#define BX_KEY_SHIFT_R 15 -#define BX_KEY_CAPS_LOCK 16 -#define BX_KEY_NUM_LOCK 17 -#define BX_KEY_ALT_L 18 -#define BX_KEY_ALT_R 19 - -#define BX_KEY_A 20 -#define BX_KEY_B 21 -#define BX_KEY_C 22 -#define BX_KEY_D 23 -#define BX_KEY_E 24 -#define BX_KEY_F 25 -#define BX_KEY_G 26 -#define BX_KEY_H 27 -#define BX_KEY_I 28 -#define BX_KEY_J 29 -#define BX_KEY_K 30 -#define BX_KEY_L 31 -#define BX_KEY_M 32 -#define BX_KEY_N 33 -#define BX_KEY_O 34 -#define BX_KEY_P 35 -#define BX_KEY_Q 36 -#define BX_KEY_R 37 -#define BX_KEY_S 38 -#define BX_KEY_T 39 -#define BX_KEY_U 40 -#define BX_KEY_V 41 -#define BX_KEY_W 42 -#define BX_KEY_X 43 -#define BX_KEY_Y 44 -#define BX_KEY_Z 45 - -#define BX_KEY_0 46 -#define BX_KEY_1 47 -#define BX_KEY_2 48 -#define BX_KEY_3 49 -#define BX_KEY_4 50 -#define BX_KEY_5 51 -#define BX_KEY_6 52 -#define BX_KEY_7 53 -#define BX_KEY_8 54 -#define BX_KEY_9 55 - -#define BX_KEY_ESC 56 - -#define BX_KEY_SPACE 57 -#define BX_KEY_SINGLE_QUOTE 58 -#define BX_KEY_COMMA 59 -#define BX_KEY_PERIOD 60 -#define BX_KEY_SLASH 61 - -#define BX_KEY_SEMICOLON 62 -#define BX_KEY_EQUALS 63 - -#define BX_KEY_LEFT_BRACKET 64 -#define BX_KEY_BACKSLASH 65 -#define BX_KEY_RIGHT_BRACKET 66 -#define BX_KEY_MINUS 67 -#define BX_KEY_GRAVE 68 - -#define BX_KEY_BACKSPACE 69 -#define BX_KEY_ENTER 70 -#define BX_KEY_TAB 71 - -#define BX_KEY_LEFT_BACKSLASH 72 -#define BX_KEY_PRINT 73 -#define BX_KEY_SCRL_LOCK 74 -#define BX_KEY_PAUSE 75 - -#define BX_KEY_INSERT 76 -#define BX_KEY_DELETE 77 -#define BX_KEY_HOME 78 -#define BX_KEY_END 79 -#define BX_KEY_PAGE_UP 80 -#define BX_KEY_PAGE_DOWN 81 - -#define BX_KEY_KP_ADD 82 -#define BX_KEY_KP_SUBTRACT 83 -#define BX_KEY_KP_END 84 -#define BX_KEY_KP_DOWN 85 -#define BX_KEY_KP_PAGE_DOWN 86 -#define BX_KEY_KP_LEFT 87 -#define BX_KEY_KP_RIGHT 88 -#define BX_KEY_KP_HOME 89 -#define BX_KEY_KP_UP 90 -#define BX_KEY_KP_PAGE_UP 91 -#define BX_KEY_KP_INSERT 92 -#define BX_KEY_KP_DELETE 93 -#define BX_KEY_KP_5 94 - -#define BX_KEY_UP 95 -#define BX_KEY_DOWN 96 -#define BX_KEY_LEFT 97 -#define BX_KEY_RIGHT 98 - -#define BX_KEY_KP_ENTER 99 -#define BX_KEY_KP_MULTIPLY 100 -#define BX_KEY_KP_DIVIDE 101 - -#define BX_KEY_WIN_L 102 -#define BX_KEY_WIN_R 103 -#define BX_KEY_MENU 104 - -#define BX_KEY_ALT_SYSREQ 105 -#define BX_KEY_CTRL_BREAK 106 - -#define BX_KEY_INT_BACK 107 -#define BX_KEY_INT_FORWARD 108 -#define BX_KEY_INT_STOP 109 -#define BX_KEY_INT_MAIL 110 -#define BX_KEY_INT_SEARCH 111 -#define BX_KEY_INT_FAV 112 -#define BX_KEY_INT_HOME 113 - -#define BX_KEY_POWER_MYCOMP 114 -#define BX_KEY_POWER_CALC 115 -#define BX_KEY_POWER_SLEEP 116 -#define BX_KEY_POWER_POWER 117 -#define BX_KEY_POWER_WAKE 118 - -#define BX_KEY_NBKEYS 119 -// If you add BX_KEYs Please update -// - BX_KEY_NBKEYS -// - the scancodes table in the file iodev/scancodes.cc -// - the bx_key_symbol table in the file gui/keymap.cc - - -/////////////// GUI plugin support - -// Define macro to supply gui plugin code. This macro is called once in GUI to -// supply the plugin initialization methods. Since it is nearly identical for -// each gui module, the macro is easier to maintain than pasting the same code -// in each one. -// -// Each gui should declare a class pointer called "theGui" which is derived -// from bx_gui_c, before calling this macro. For example, the SDL port -// says: -// static bx_sdl_gui_c *theGui; - -#define IMPLEMENT_GUI_PLUGIN_CODE(gui_name) \ - int lib##gui_name##_LTX_plugin_init(plugin_t *plugin, \ - plugintype_t type, int argc, char *argv[]) { \ - genlog->info("installing %s module as the Bochs GUI", #gui_name); \ - theGui = new bx_##gui_name##_gui_c (); \ - bx_gui = theGui; \ - return(0); /* Success */ \ - } \ - void lib##gui_name##_LTX_plugin_fini(void) { } diff --git a/tools/ioemu/gui/icon_bochs.h b/tools/ioemu/gui/icon_bochs.h deleted file mode 100644 index 36669fec53..0000000000 --- a/tools/ioemu/gui/icon_bochs.h +++ /dev/null @@ -1,40 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: icon_bochs.h,v 1.3 2001/10/03 13:10:37 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -#define bochs_icon_width 32 -#define bochs_icon_height 32 -static unsigned char bochs_icon_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, - 0xe0, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, - 0xfc, 0xc7, 0xe3, 0x3f, 0xfc, 0xc7, 0xe3, 0x3f, 0xfc, 0xc3, 0xc3, 0x3f, - 0xfc, 0xc3, 0xc3, 0x3f, 0xf8, 0xc1, 0x83, 0x1f, 0xf0, 0xc0, 0x03, 0x0f, - 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, - 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, - 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0xf0, 0xc0, 0x03, 0x0f, - 0xf8, 0xc1, 0x83, 0x1f, 0xfc, 0xc3, 0xc3, 0x3f, 0xfc, 0xc3, 0xc3, 0x3f, - 0xfc, 0xc7, 0xe3, 0x3f, 0xfc, 0xc7, 0xe3, 0x3f, 0xf8, 0xff, 0xff, 0x1f, - 0xf8, 0xff, 0xff, 0x1f, 0xe0, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; diff --git a/tools/ioemu/gui/icon_bochs.xpm b/tools/ioemu/gui/icon_bochs.xpm deleted file mode 100644 index f895743fcf..0000000000 --- a/tools/ioemu/gui/icon_bochs.xpm +++ /dev/null @@ -1,45 +0,0 @@ -/* XPM */ -static char *icon_bochs_xpm[] = { -/* columns rows colors chars-per-pixel */ -"32 32 7 1", -" c black", -". c #800000", -"X c #808000", -"o c yellow", -"O c #808080", -"+ c #c0c0c0", -"@ c None", -/* pixels */ -"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", -"@@@@@@@@@@. +@@@+ +@@@@@@@@@", -"@@@@@@@@ Oo @+ .@@@@@@@@", -"@@@@@@ ooooo ooo. @@@@@@@", -"@@@@ oooooo. oooooX @@@@@", -"@+ XoooooO XX ooooooo O@@@", -"+ oooooO XXXX X ooooooo @@", -"@ ooo XXXXXX XX ooooooX ", -"@@. XXXXXXXX XXX Xooooo. ", -"@@@@ OXXXXXXXXX XXXXXO oO .@", -"@@@@ .XXXXXXX XXXXXXX. @@@", -"@+ oo XXXX XXXXXXXX @@@", -"@ ooooo XXXXXX O", -"@@O oooooo OXXXX. XX Oooo ", -"@@@@ .ooooo. XXXXX oooo O@", -"@@@@ Oooooo XX. .ooo @@@", -"@@@@ XX oooooo .oooo. @@@@", -"@@@@ ooXX . ooO o @@@@", -"@@@@ oooXX. .Xo XX XXo @@@@", -"@@@@ ooooXXXXXXXo XXXX.XXoo @@@@", -"@@@+ oooooooooooo XooXXXooo @@@@", -"@@@. oooooooooooo Xooooooo @@@@", -"@@@+ oooooooooo XoooooX .@@@@@", -"@@@@@O XoooooooX ooooo +@@@@@@", -"@@@@@@@ ooooooX oooX @@@@@@@@", -"@@@@@@@@@ ooooX oo @@@@@@@@@", -"@@@@@@@@@@. Ooo. O@@@@@@@@@@", -"@@@@@@@@@@@@ @@@@@@@@@@@@", -"@@@@@@@@@@@@@@O O@@@@@@@@@@@@@", -"@@@@@@@@@@@@@@@@+@@@@@@@@@@@@@@@", -"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@", -"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@" -}; diff --git a/tools/ioemu/gui/keymap.cc b/tools/ioemu/gui/keymap.cc deleted file mode 100644 index 8013693c8a..0000000000 --- a/tools/ioemu/gui/keymap.cc +++ /dev/null @@ -1,330 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: keymap.cc,v 1.16 2003/10/11 10:43:24 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -///////////////////////////////////////////////////////////////////////// -// -// Todo -// . Currently supported by sdl, wxGTK and x11. Check if other guis need mapping. -// . Tables look-up should be optimised. -// - -#include "bochs.h" - -// Table of bochs "BX_KEY_*" symbols -// the table must be in BX_KEY_* order -char *bx_key_symbol[BX_KEY_NBKEYS] = { - "BX_KEY_CTRL_L", "BX_KEY_SHIFT_L", "BX_KEY_F1", - "BX_KEY_F2", "BX_KEY_F3", "BX_KEY_F4", - "BX_KEY_F5", "BX_KEY_F6", "BX_KEY_F7", - "BX_KEY_F8", "BX_KEY_F9", "BX_KEY_F10", - "BX_KEY_F11", "BX_KEY_F12", "BX_KEY_CTRL_R", - "BX_KEY_SHIFT_R", "BX_KEY_CAPS_LOCK", "BX_KEY_NUM_LOCK", - "BX_KEY_ALT_L", "BX_KEY_ALT_R", "BX_KEY_A", - "BX_KEY_B", "BX_KEY_C", "BX_KEY_D", - "BX_KEY_E", "BX_KEY_F", "BX_KEY_G", - "BX_KEY_H", "BX_KEY_I", "BX_KEY_J", - "BX_KEY_K", "BX_KEY_L", "BX_KEY_M", - "BX_KEY_N", "BX_KEY_O", "BX_KEY_P", - "BX_KEY_Q", "BX_KEY_R", "BX_KEY_S", - "BX_KEY_T", "BX_KEY_U", "BX_KEY_V", - "BX_KEY_W", "BX_KEY_X", "BX_KEY_Y", - "BX_KEY_Z", "BX_KEY_0", "BX_KEY_1", - "BX_KEY_2", "BX_KEY_3", "BX_KEY_4", - "BX_KEY_5", "BX_KEY_6", "BX_KEY_7", - "BX_KEY_8", "BX_KEY_9", "BX_KEY_ESC", - "BX_KEY_SPACE", "BX_KEY_SINGLE_QUOTE", "BX_KEY_COMMA", - "BX_KEY_PERIOD", "BX_KEY_SLASH", "BX_KEY_SEMICOLON", - "BX_KEY_EQUALS", "BX_KEY_LEFT_BRACKET", "BX_KEY_BACKSLASH", - "BX_KEY_RIGHT_BRACKET", "BX_KEY_MINUS", "BX_KEY_GRAVE", - "BX_KEY_BACKSPACE", "BX_KEY_ENTER", "BX_KEY_TAB", - "BX_KEY_LEFT_BACKSLASH", "BX_KEY_PRINT", "BX_KEY_SCRL_LOCK", - "BX_KEY_PAUSE", "BX_KEY_INSERT", "BX_KEY_DELETE", - "BX_KEY_HOME", "BX_KEY_END", "BX_KEY_PAGE_UP", - "BX_KEY_PAGE_DOWN", "BX_KEY_KP_ADD", "BX_KEY_KP_SUBTRACT", - "BX_KEY_KP_END", "BX_KEY_KP_DOWN", "BX_KEY_KP_PAGE_DOWN", - "BX_KEY_KP_LEFT", "BX_KEY_KP_RIGHT", "BX_KEY_KP_HOME", - "BX_KEY_KP_UP", "BX_KEY_KP_PAGE_UP", "BX_KEY_KP_INSERT", - "BX_KEY_KP_DELETE", "BX_KEY_KP_5", "BX_KEY_UP", - "BX_KEY_DOWN", "BX_KEY_LEFT", "BX_KEY_RIGHT", - "BX_KEY_KP_ENTER", "BX_KEY_KP_MULTIPLY", "BX_KEY_KP_DIVIDE", - "BX_KEY_WIN_L", "BX_KEY_WIN_R", "BX_KEY_MENU", - "BX_KEY_ALT_SYSREQ", "BX_KEY_CTRL_BREAK", "BX_KEY_INT_BACK", - "BX_KEY_INT_FORWARD", "BX_KEY_INT_STOP", "BX_KEY_INT_MAIL", - "BX_KEY_INT_SEARCH", "BX_KEY_INT_FAV", "BX_KEY_INT_HOME", - "BX_KEY_POWER_MYCOMP", "BX_KEY_POWER_CALC", "BX_KEY_POWER_SLEEP", - "BX_KEY_POWER_POWER", "BX_KEY_POWER_WAKE", - }; - -bx_keymap_c bx_keymap; - -#define LOG_THIS bx_keymap. - -bx_keymap_c::bx_keymap_c(void) -{ - put("KMAP"); - - keymapCount = 0; - keymapTable = (BXKeyEntry *)NULL; - -} - -bx_keymap_c::~bx_keymap_c(void) -{ - if(keymapTable != NULL) { - free(keymapTable); - keymapTable = (BXKeyEntry *)NULL; - } - keymapCount = 0; -} - - void -bx_keymap_c::loadKeymap(Bit32u stringToSymbol(const char*)) -{ - if(bx_options.keyboard.OuseMapping->get()) { - loadKeymap(stringToSymbol,bx_options.keyboard.Okeymap->getptr()); - } -} - - -bx_bool -bx_keymap_c::isKeymapLoaded () -{ - return (keymapCount > 0); -} - - -/////////////////// -// I'll add these to the keymap object in a minute. -static unsigned char *lineptr = NULL; -static int lineCount; - -static void -init_parse () -{ - lineCount = 0; -} - -static void -init_parse_line (char *line_to_parse) -{ - // chop off newline - lineptr = (unsigned char *)line_to_parse; - char *nl; - if( (nl = strchr(line_to_parse,'\n')) != NULL) { - *nl = 0; - } -} - -static Bit32s -get_next_word (char *output) -{ - char *copyp = output; - // find first nonspace - while (*lineptr && isspace (*lineptr)) - lineptr++; - if (!*lineptr) - return -1; // nothing but spaces until end of line - if (*lineptr == '#') - return -1; // nothing but a comment - // copy nonspaces into the output - while (*lineptr && !isspace (*lineptr)) - *copyp++ = *lineptr++; - *copyp=0; // null terminate the copy - // there must be at least one nonspace, since that's why we stopped the - // first loop! - BX_ASSERT (copyp != output); - return 0; -} - -static Bit32s -get_next_keymap_line (FILE *fp, char *bxsym, char *modsym, Bit32s *ascii, char *hostsym) -{ - char line[256]; - char buf[256]; - line[0] = 0; - while (1) { - lineCount++; - if (!fgets(line, sizeof(line)-1, fp)) return -1; // EOF - init_parse_line (line); - if (get_next_word (bxsym) >= 0) { - modsym[0] = 0; - char *p; - if ((p = strchr (bxsym, '+')) != NULL) { - *p = 0; // truncate bxsym. - p++; // move one char beyond the + - strcpy (modsym, p); // copy the rest to modsym - } - if (get_next_word (buf) < 0) { - BX_PANIC (("keymap line %d: expected 3 columns", lineCount)); - return -1; - } - if (buf[0] == '\'' && buf[2] == '\'' && buf[3]==0) { - *ascii = (Bit8u) buf[1]; - } else if (!strcmp(buf, "space")) { - *ascii = ' '; - } else if (!strcmp(buf, "return")) { - *ascii = '\n'; - } else if (!strcmp(buf, "tab")) { - *ascii = '\t'; - } else if (!strcmp(buf, "backslash")) { - *ascii = '\\'; - } else if (!strcmp(buf, "apostrophe")) { - *ascii = '\''; - } else if (!strcmp(buf, "none")) { - *ascii = -1; - } else { - BX_PANIC (("keymap line %d: ascii equivalent is \"%s\" but it must be char constant like 'x', or one of space,tab,return,none", lineCount, buf)); - } - if (get_next_word (hostsym) < 0) { - BX_PANIC (("keymap line %d: expected 3 columns", lineCount)); - return -1; - } - return 0; - } - // no words on this line, keep reading. - } -} - - void -bx_keymap_c::loadKeymap(Bit32u stringToSymbol(const char*), const char* filename) -{ - FILE *keymapFile; - char baseSym[256], modSym[256], hostSym[256]; - Bit32s ascii; - Bit32u baseKey, modKey, hostKey; - struct stat status; - - if (stat(filename, &status)) { - BX_PANIC(("Can not stat keymap file '%s'.",filename)); - } - - if (!(S_ISREG(status.st_mode))) { - BX_PANIC(("Keymap file '%s' is not a file",filename)); - } - - if((keymapFile = fopen(filename,"r"))==NULL) { - BX_PANIC(("Can not open keymap file '%s'.",filename)); - } - - BX_INFO(("Loading keymap from '%s'",filename)); - init_parse (); - - // Read keymap file one line at a time - while(1) { - if (get_next_keymap_line (keymapFile, - baseSym, modSym, &ascii, hostSym) < 0) { break; } - - - // convert X_KEY_* symbols to values - baseKey = convertStringToBXKey(baseSym); - modKey = convertStringToBXKey(modSym); - hostKey = 0; - if (stringToSymbol != NULL) - hostKey = stringToSymbol(hostSym); - - BX_DEBUG (("baseKey='%s' (%d), modSym='%s' (%d), ascii=%d, guisym='%s' (%d)", baseSym, baseKey, modSym, modKey, ascii, hostSym, hostKey)); - - // Check if data is valid - if( baseKey==BX_KEYMAP_UNKNOWN ) { - BX_PANIC (("line %d: unknown BX_KEY constant '%s'",lineCount,baseSym)); - continue; - } - - if( hostKey==BX_KEYMAP_UNKNOWN ) { - BX_PANIC (("line %d: unknown host key name '%s'",lineCount,hostSym)); - continue; - } - - keymapTable=(BXKeyEntry*)realloc(keymapTable,(keymapCount+1) * sizeof(BXKeyEntry)); - - if(keymapTable==NULL) - BX_PANIC(("Can not allocate memory for keymap table.")); - - keymapTable[keymapCount].baseKey=baseKey; - keymapTable[keymapCount].modKey=modKey; - keymapTable[keymapCount].ascii=ascii; - keymapTable[keymapCount].hostKey=hostKey; - - keymapCount++; - } - - BX_INFO(("Loaded %d symbols",keymapCount)); - - fclose(keymapFile); -} - - Bit32u -bx_keymap_c::convertStringToBXKey(const char* string) -{ - Bit16u i; - - // We look through the bx_key_symbol table to find the searched string - for (i=0; i) -{ - chop; - s/^ *//; - if (/^#/ || /^ *$/) { print "$_\n"; next;} - ($key, $equals, $xksym) = split (/ +/); - printf ("%-45s %-10s %s\n", $key, 'none', "XK_$xksym"); -} diff --git a/tools/ioemu/gui/keymaps/sdl-pc-de.map b/tools/ioemu/gui/keymaps/sdl-pc-de.map deleted file mode 100644 index de4fd59cd8..0000000000 --- a/tools/ioemu/gui/keymaps/sdl-pc-de.map +++ /dev/null @@ -1,222 +0,0 @@ -# Bochs Keymap file -# $Id: sdl-pc-de.map,v 1.2 2002/10/24 21:06:55 bdenney Exp $ -# Target: PC(x86) keyboard, DE keymap, SDL gui on X11 -# Author: Volker Ruppert -# -# The keymap file describes the layout of a keyboard, and how it translates -# into Bochs key codes. -# -# Format: -# BX_Keysym ASCII_equivalent Host_key_name -# -# Or, for keys that require modifiers: -# BX_Keysym+BX_Modifier ASCII_equivalent Host_key_name -# -# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in -# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it -# could be any key. Presently a maximum of one modifier is supported, but this -# could be changed in keymap.h (structure def has only one slot for modifier), -# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1 -# modifier). -# -# The ASCII_equivalent must be either apostrophe + one character + apostrophe, -# or one of these keywords: space, return, tab, backslash, apostrophe, none. -# This format is designed to look like a char constant in C, but it's a very -# simple parser. There's no concept of backslash being an escape char. The -# backslash and apostrophe entries are provided for aesthetic purposes only: no -# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are -# ugly. -# -# Host_key_name is the name of the key combination according to the gui library -# (X windows, SDL, etc). Each GUI module must provide a function that converts -# these host key names into numbers. A pointer to the conversion function is -# passed to loadKeymap(), and it is used when parsing the keymap file. As the -# keymap file is parsed, the conversion function is called for each host key -# name, to convert it into a number. Only the number is stored. If the host -# key name is not found, the conversion function returns BX_KEYMAP_UNKNOWN, and -# the keymap code will panic, like this: -# -# [KMAP ] line 51: unknown host key name 'SDLK_PAREN_RIGHT' -# -# If this happens, you must edit the keymap file, and either correct the host -# key name or comment out that line. -# - -BX_KEY_0 '0' SDLK_0 -BX_KEY_0+BX_KEY_SHIFT_L '=' SDLK_EQUALS -BX_KEY_1 '1' SDLK_1 -BX_KEY_1+BX_KEY_SHIFT_L '!' SDLK_EXCLAIM -BX_KEY_2 '2' SDLK_2 -BX_KEY_2+BX_KEY_ALT_R '²' SDLK_2 -BX_KEY_2+BX_KEY_SHIFT_L '"' SDLK_QUOTEDBL -BX_KEY_3 '3' SDLK_3 -BX_KEY_3+BX_KEY_SHIFT_L '§' SDLK_3 -BX_KEY_4 '4' SDLK_4 -BX_KEY_4+BX_KEY_SHIFT_L '$' SDLK_DOLLAR -BX_KEY_4+BX_KEY_ALT_R '¼' SDLK_4 -BX_KEY_5 '5' SDLK_5 -BX_KEY_5+BX_KEY_ALT_R '½' SDLK_5 -BX_KEY_5+BX_KEY_SHIFT_L '%' SDLK_5 -BX_KEY_6 '6' SDLK_6 -BX_KEY_6+BX_KEY_SHIFT_L '&' SDLK_AMPERSAND -BX_KEY_7 '7' SDLK_7 -BX_KEY_7+BX_KEY_ALT_R '{' SDLK_7 -BX_KEY_7+BX_KEY_SHIFT_L '/' SDLK_SLASH -BX_KEY_8 '8' SDLK_8 -BX_KEY_8+BX_KEY_ALT_R '[' SDLK_LEFTBRACKET -BX_KEY_8+BX_KEY_SHIFT_L '(' SDLK_LEFTPAREN -BX_KEY_9 '9' SDLK_9 -BX_KEY_9+BX_KEY_ALT_R ']' SDLK_RIGHTBRACKET -BX_KEY_9+BX_KEY_SHIFT_L ')' SDLK_RIGHTPAREN -BX_KEY_A+BX_KEY_SHIFT_L 'A' SDLK_a -BX_KEY_A 'a' SDLK_a -BX_KEY_A+BX_KEY_ALT_R 'æ' SDLK_a -BX_KEY_B+BX_KEY_SHIFT_L 'B' SDLK_b -BX_KEY_B 'b' SDLK_b -BX_KEY_C+BX_KEY_SHIFT_L 'C' SDLK_c -BX_KEY_C 'c' SDLK_c -BX_KEY_C+BX_KEY_ALT_R '¢' SDLK_c -BX_KEY_D+BX_KEY_SHIFT_L 'D' SDLK_d -BX_KEY_D 'd' SDLK_d -BX_KEY_E+BX_KEY_SHIFT_L 'E' SDLK_e -BX_KEY_E+BX_KEY_ALT_R none SDLK_EURO -BX_KEY_E 'e' SDLK_e -BX_KEY_F+BX_KEY_SHIFT_L 'F' SDLK_f -BX_KEY_F 'f' SDLK_f -BX_KEY_G+BX_KEY_SHIFT_L 'G' SDLK_g -BX_KEY_G 'g' SDLK_g -BX_KEY_H+BX_KEY_SHIFT_L 'H' SDLK_h -BX_KEY_H 'h' SDLK_h -BX_KEY_I+BX_KEY_SHIFT_L 'I' SDLK_i -BX_KEY_I 'i' SDLK_i -BX_KEY_J+BX_KEY_SHIFT_L 'J' SDLK_j -BX_KEY_J 'j' SDLK_j -BX_KEY_K+BX_KEY_SHIFT_L 'K' SDLK_k -BX_KEY_K 'k' SDLK_k -BX_KEY_L+BX_KEY_SHIFT_L 'L' SDLK_l -BX_KEY_L 'l' SDLK_l -BX_KEY_M+BX_KEY_SHIFT_L 'M' SDLK_m -BX_KEY_M 'm' SDLK_m -BX_KEY_M+BX_KEY_ALT_R 'µ' SDLK_m -BX_KEY_N+BX_KEY_SHIFT_L 'N' SDLK_n -BX_KEY_N 'n' SDLK_n -BX_KEY_O+BX_KEY_SHIFT_L 'O' SDLK_o -BX_KEY_O 'o' SDLK_o -BX_KEY_O+BX_KEY_ALT_R 'ø' SDLK_o -BX_KEY_P+BX_KEY_SHIFT_L 'P' SDLK_p -BX_KEY_P 'p' SDLK_p -BX_KEY_Q+BX_KEY_SHIFT_L 'Q' SDLK_q -BX_KEY_Q+BX_KEY_ALT_R '@' SDLK_AT -BX_KEY_Q 'q' SDLK_q -BX_KEY_R+BX_KEY_SHIFT_L 'R' SDLK_r -BX_KEY_R+BX_KEY_ALT_R '¶' SDLK_r -BX_KEY_R 'r' SDLK_r -BX_KEY_S+BX_KEY_SHIFT_L 'S' SDLK_s -BX_KEY_S 's' SDLK_s -BX_KEY_T+BX_KEY_SHIFT_L 'T' SDLK_t -BX_KEY_T 't' SDLK_t -BX_KEY_U+BX_KEY_SHIFT_L 'U' SDLK_u -BX_KEY_U 'u' SDLK_u -BX_KEY_V+BX_KEY_SHIFT_L 'V' SDLK_v -BX_KEY_V 'v' SDLK_v -BX_KEY_W+BX_KEY_SHIFT_L 'W' SDLK_w -BX_KEY_W 'w' SDLK_w -BX_KEY_X+BX_KEY_SHIFT_L 'X' SDLK_x -BX_KEY_X+BX_KEY_ALT_R '»' SDLK_x -BX_KEY_X 'x' SDLK_x -BX_KEY_Y+BX_KEY_SHIFT_L 'Z' SDLK_z -BX_KEY_Y 'z' SDLK_z -BX_KEY_Z+BX_KEY_SHIFT_L 'Y' SDLK_y -BX_KEY_Z+BX_KEY_ALT_R '«' SDLK_y -BX_KEY_Z 'y' SDLK_y -BX_KEY_F1 none SDLK_F1 -BX_KEY_F2 none SDLK_F2 -BX_KEY_F3 none SDLK_F3 -BX_KEY_F4 none SDLK_F4 -BX_KEY_F5 none SDLK_F5 -BX_KEY_F6 none SDLK_F6 -BX_KEY_F7 none SDLK_F7 -BX_KEY_F8 none SDLK_F8 -BX_KEY_F9 none SDLK_F9 -BX_KEY_F10 none SDLK_F10 -BX_KEY_F11 none SDLK_F11 -BX_KEY_F12 none SDLK_F12 -BX_KEY_ALT_L none SDLK_LALT -BX_KEY_ALT_L none SDLK_LMETA -BX_KEY_ALT_R none SDLK_RALT -BX_KEY_ALT_R none SDLK_MODE -BX_KEY_BACKSLASH apostrophe SDLK_QUOTE -BX_KEY_BACKSLASH '#' SDLK_HASH -BX_KEY_BACKSPACE none SDLK_BACKSPACE -BX_KEY_CAPS_LOCK none SDLK_CAPSLOCK -BX_KEY_COMMA ',' SDLK_COMMA -BX_KEY_COMMA+BX_KEY_SHIFT_L ';' SDLK_SEMICOLON -BX_KEY_CTRL_L none SDLK_LCTRL -BX_KEY_CTRL_R none SDLK_RCTRL -BX_KEY_DELETE none SDLK_DELETE -BX_KEY_DOWN none SDLK_DOWN -BX_KEY_END none SDLK_END -BX_KEY_ENTER return SDLK_RETURN -BX_KEY_EQUALS none SDLK_WORLD_20 -BX_KEY_EQUALS+BX_KEY_ALT_R '¸' SDLK_WORLD_20 -BX_KEY_EQUALS+BX_KEY_SHIFT_L '`' SDLK_WORLD_20 -BX_KEY_ESC none SDLK_ESCAPE -BX_KEY_GRAVE '^' SDLK_CARET -BX_KEY_GRAVE+BX_KEY_SHIFT_L '°' SDLK_CARET -BX_KEY_GRAVE+BX_KEY_ALT_R '¬' SDLK_CARET -BX_KEY_HOME none SDLK_HOME -BX_KEY_INSERT none SDLK_INSERT -BX_KEY_KP_5 none SDLK_KP5 -BX_KEY_KP_ADD none SDLK_KP_PLUS -BX_KEY_KP_DELETE none SDLK_KP_PERIOD -BX_KEY_KP_DIVIDE none SDLK_KP_DIVIDE -BX_KEY_KP_DOWN none SDLK_KP2 -BX_KEY_KP_END none SDLK_KP1 -BX_KEY_KP_ENTER none SDLK_KP_ENTER -BX_KEY_KP_HOME none SDLK_KP7 -BX_KEY_KP_INSERT none SDLK_KP0 -BX_KEY_KP_LEFT none SDLK_KP4 -BX_KEY_KP_MULTIPLY none SDLK_KP_MULTIPLY -BX_KEY_KP_PAGE_DOWN none SDLK_KP3 -BX_KEY_KP_PAGE_UP none SDLK_KP9 -BX_KEY_KP_RIGHT none SDLK_KP6 -BX_KEY_KP_SUBTRACT none SDLK_KP_MINUS -BX_KEY_KP_UP none SDLK_KP8 -BX_KEY_LEFT none SDLK_LEFT -BX_KEY_LEFT_BACKSLASH+BX_KEY_ALT_R '|' SDLK_LESS -BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '>' SDLK_GREATER -BX_KEY_LEFT_BACKSLASH '<' SDLK_LESS -BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L 'Ü' SDLK_WORLD_92 -BX_KEY_LEFT_BRACKET 'ü' SDLK_WORLD_92 -BX_KEY_MENU none SDLK_MENU -BX_KEY_MINUS+BX_KEY_ALT_L backslash SDLK_BACKSLASH -BX_KEY_MINUS+BX_KEY_SHIFT_L '?' SDLK_QUESTION -BX_KEY_MINUS 'ß' SDLK_WORLD_63 -BX_KEY_NUM_LOCK none SDLK_NUMLOCK -BX_KEY_PAGE_DOWN none SDLK_PAGEDOWN -BX_KEY_PAGE_UP none SDLK_PAGEUP -BX_KEY_PAUSE none SDLK_BREAK -BX_KEY_PAUSE none SDLK_PAUSE -BX_KEY_PERIOD+BX_KEY_SHIFT_L ':' SDLK_COLON -BX_KEY_PERIOD '.' SDLK_PERIOD -BX_KEY_PERIOD+BX_KEY_ALT_L '·' SDLK_PERIOD -BX_KEY_PRINT none SDLK_PRINT -BX_KEY_PRINT none SDLK_SYSREQ -BX_KEY_RIGHT none SDLK_RIGHT -BX_KEY_RIGHT_BRACKET+BX_KEY_ALT_R '~' SDLK_PLUS -BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '*' SDLK_PLUS -BX_KEY_RIGHT_BRACKET '+' SDLK_PLUS -BX_KEY_SCRL_LOCK none SDLK_SCROLLOCK -BX_KEY_SEMICOLON+BX_KEY_SHIFT_L 'Ö' SDLK_WORLD_86 -BX_KEY_SEMICOLON 'ö' SDLK_WORLD_86 -BX_KEY_SHIFT_L none SDLK_LSHIFT -BX_KEY_SHIFT_R none SDLK_RSHIFT -BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L 'Ä' SDLK_WORLD_68 -BX_KEY_SINGLE_QUOTE 'ä' SDLK_WORLD_68 -BX_KEY_SLASH '-' SDLK_MINUS -BX_KEY_SLASH+BX_KEY_SHIFT_L '_' SDLK_UNDERSCORE -BX_KEY_SPACE space SDLK_SPACE -BX_KEY_TAB tab SDLK_TAB -BX_KEY_UP none SDLK_UP -BX_KEY_WIN_L none SDLK_LSUPER -BX_KEY_WIN_R none SDLK_RSUPER diff --git a/tools/ioemu/gui/keymaps/sdl-pc-us.map b/tools/ioemu/gui/keymaps/sdl-pc-us.map deleted file mode 100644 index 3440992b50..0000000000 --- a/tools/ioemu/gui/keymaps/sdl-pc-us.map +++ /dev/null @@ -1,211 +0,0 @@ -# Bochs Keymap file -# $Id: sdl-pc-us.map,v 1.2 2002/10/24 21:06:55 bdenney Exp $ -# Target: PC(x86) keyboard, US keymap, SDL gui -# Author: Bryce Denney -# -# The keymap file describes the layout of a keyboard, and how it translates -# into Bochs key codes. -# -# Format: -# BX_Keysym ASCII_equivalent Host_key_name -# -# Or, for keys that require modifiers: -# BX_Keysym+BX_Modifier ASCII_equivalent Host_key_name -# -# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in -# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it -# could be any key. Presently a maximum of one modifier is supported, but this -# could be changed in keymap.h (structure def has only one slot for modifier), -# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1 -# modifier). -# -# The ASCII_equivalent must be either apostrophe + one character + apostrophe, -# or one of these keywords: space, return, tab, backslash, apostrophe, none. -# This format is designed to look like a char constant in C, but it's a very -# simple parser. There's no concept of backslash being an escape char. The -# backslash and apostrophe entries are provided for aesthetic purposes only: no -# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are -# ugly. -# -# Host_key_name is the name of the key combination according to the gui library -# (X windows, SDL, etc). Each GUI module must provide a function that converts -# these host key names into numbers. A pointer to the conversion function is -# passed to loadKeymap(), and it is used when parsing the keymap file. As the -# keymap file is parsed, the conversion function is called for each host key -# name, to convert it into a number. Only the number is stored. If the host -# key name is not found, the conversion function returns BX_KEYMAP_UNKNOWN, and -# the keymap code will panic, like this: -# -# [KMAP ] line 51: unknown host key name 'SDLK_PAREN_RIGHT' -# -# If this happens, you must edit the keymap file, and either correct the host -# key name or comment out that line. -# - -BX_KEY_0 '0' SDLK_0 -BX_KEY_0+BX_KEY_SHIFT_L ')' SDLK_RIGHTPAREN -BX_KEY_1 '1' SDLK_1 -BX_KEY_1+BX_KEY_SHIFT_L '!' SDLK_EXCLAIM -BX_KEY_2 '2' SDLK_2 -BX_KEY_2+BX_KEY_SHIFT_L '@' SDLK_AT -BX_KEY_3 '3' SDLK_3 -BX_KEY_3+BX_KEY_SHIFT_L '#' SDLK_HASH -BX_KEY_4 '4' SDLK_4 -BX_KEY_4+BX_KEY_SHIFT_L '$' SDLK_DOLLAR -BX_KEY_5 '5' SDLK_5 -#BX_KEY_5+BX_KEY_SHIFT_L '%' SDLK_PERCENT -BX_KEY_6 '6' SDLK_6 -BX_KEY_6+BX_KEY_SHIFT_L '^' SDLK_CARET -BX_KEY_7 '7' SDLK_7 -BX_KEY_7+BX_KEY_SHIFT_L '&' SDLK_AMPERSAND -BX_KEY_8 '8' SDLK_8 -BX_KEY_8+BX_KEY_SHIFT_L '*' SDLK_ASTERISK -BX_KEY_9 '9' SDLK_9 -BX_KEY_9+BX_KEY_SHIFT_L '(' SDLK_LEFTPAREN -BX_KEY_A+BX_KEY_SHIFT_L 'A' SDLK_a -BX_KEY_A 'a' SDLK_a -BX_KEY_B+BX_KEY_SHIFT_L 'B' SDLK_b -BX_KEY_B 'b' SDLK_b -BX_KEY_C+BX_KEY_SHIFT_L 'C' SDLK_c -BX_KEY_C 'c' SDLK_c -BX_KEY_D+BX_KEY_SHIFT_L 'D' SDLK_d -BX_KEY_D 'd' SDLK_d -BX_KEY_E+BX_KEY_SHIFT_L 'E' SDLK_e -BX_KEY_E 'e' SDLK_e -BX_KEY_F+BX_KEY_SHIFT_L 'F' SDLK_f -BX_KEY_F 'f' SDLK_f -BX_KEY_G+BX_KEY_SHIFT_L 'G' SDLK_g -BX_KEY_G 'g' SDLK_g -BX_KEY_H+BX_KEY_SHIFT_L 'H' SDLK_h -BX_KEY_H 'h' SDLK_h -BX_KEY_I+BX_KEY_SHIFT_L 'I' SDLK_i -BX_KEY_I 'i' SDLK_i -BX_KEY_J+BX_KEY_SHIFT_L 'J' SDLK_j -BX_KEY_J 'j' SDLK_j -BX_KEY_K+BX_KEY_SHIFT_L 'K' SDLK_k -BX_KEY_K 'k' SDLK_k -BX_KEY_L+BX_KEY_SHIFT_L 'L' SDLK_l -BX_KEY_L 'l' SDLK_l -BX_KEY_M+BX_KEY_SHIFT_L 'M' SDLK_m -BX_KEY_M 'm' SDLK_m -BX_KEY_N+BX_KEY_SHIFT_L 'N' SDLK_n -BX_KEY_N 'n' SDLK_n -BX_KEY_O+BX_KEY_SHIFT_L 'O' SDLK_o -BX_KEY_O 'o' SDLK_o -BX_KEY_P+BX_KEY_SHIFT_L 'P' SDLK_p -BX_KEY_P 'p' SDLK_p -BX_KEY_Q+BX_KEY_SHIFT_L 'Q' SDLK_q -BX_KEY_Q 'q' SDLK_q -BX_KEY_R+BX_KEY_SHIFT_L 'R' SDLK_r -BX_KEY_R 'r' SDLK_r -BX_KEY_S+BX_KEY_SHIFT_L 'S' SDLK_s -BX_KEY_S 's' SDLK_s -BX_KEY_T+BX_KEY_SHIFT_L 'T' SDLK_t -BX_KEY_T 't' SDLK_t -BX_KEY_U+BX_KEY_SHIFT_L 'U' SDLK_u -BX_KEY_U 'u' SDLK_u -BX_KEY_V+BX_KEY_SHIFT_L 'V' SDLK_v -BX_KEY_V 'v' SDLK_v -BX_KEY_W+BX_KEY_SHIFT_L 'W' SDLK_w -BX_KEY_W 'w' SDLK_w -BX_KEY_X+BX_KEY_SHIFT_L 'X' SDLK_x -BX_KEY_X 'x' SDLK_x -BX_KEY_Y+BX_KEY_SHIFT_L 'Y' SDLK_y -BX_KEY_Y 'y' SDLK_y -BX_KEY_Z+BX_KEY_SHIFT_L 'Z' SDLK_z -BX_KEY_Z 'z' SDLK_z -BX_KEY_F1 none SDLK_F1 -BX_KEY_F2 none SDLK_F2 -BX_KEY_F3 none SDLK_F3 -BX_KEY_F4 none SDLK_F4 -BX_KEY_F5 none SDLK_F5 -BX_KEY_F6 none SDLK_F6 -BX_KEY_F7 none SDLK_F7 -BX_KEY_F8 none SDLK_F8 -BX_KEY_F9 none SDLK_F9 -BX_KEY_F10 none SDLK_F10 -BX_KEY_F11 none SDLK_F11 -BX_KEY_F12 none SDLK_F12 -BX_KEY_ALT_L none SDLK_LALT -BX_KEY_ALT_L none SDLK_LMETA -BX_KEY_ALT_R none SDLK_MODE -#BX_KEY_ALT_R none SDLK_Multi_key -BX_KEY_BACKSLASH backslash SDLK_BACKSLASH -#BX_KEY_BACKSLASH+BX_KEY_SHIFT_L '|' SDLK_bar -BX_KEY_BACKSPACE none SDLK_BACKSPACE -BX_KEY_CAPS_LOCK none SDLK_CAPSLOCK -BX_KEY_COMMA ',' SDLK_COMMA -BX_KEY_COMMA+BX_KEY_SHIFT_L '<' SDLK_LESS -BX_KEY_CTRL_L none SDLK_LCTRL -BX_KEY_CTRL_R none SDLK_RCTRL -BX_KEY_DELETE none SDLK_DELETE -BX_KEY_DOWN none SDLK_DOWN -BX_KEY_END none SDLK_END -BX_KEY_ENTER return SDLK_RETURN -BX_KEY_EQUALS '=' SDLK_EQUALS -BX_KEY_EQUALS+BX_KEY_SHIFT_L '+' SDLK_PLUS -BX_KEY_ESC none SDLK_ESCAPE -#BX_KEY_GRAVE+BX_KEY_SHIFT_L '~' SDLK_asciitilde -BX_KEY_GRAVE '`' SDLK_BACKQUOTE -BX_KEY_HOME none SDLK_HOME -BX_KEY_INSERT none SDLK_INSERT -BX_KEY_KP_5 none SDLK_KP5 -#BX_KEY_KP_5 none SDLK_KP_BEGIN -BX_KEY_KP_ADD none SDLK_KP_PLUS -BX_KEY_KP_DELETE none SDLK_KP_PERIOD -#BX_KEY_KP_DELETE none SDLK_KP_DELETE -BX_KEY_KP_DIVIDE none SDLK_KP_DIVIDE -BX_KEY_KP_DOWN none SDLK_KP2 -#BX_KEY_KP_DOWN none SDLK_KP_DOWN -BX_KEY_KP_END none SDLK_KP1 -#BX_KEY_KP_END none SDLK_KP_END -BX_KEY_KP_ENTER none SDLK_KP_ENTER -BX_KEY_KP_HOME none SDLK_KP7 -#BX_KEY_KP_HOME none SDLK_KP_HOME -BX_KEY_KP_INSERT none SDLK_KP0 -#BX_KEY_KP_INSERT none SDLK_KP_INSERT -BX_KEY_KP_LEFT none SDLK_KP4 -#BX_KEY_KP_LEFT none SDLK_KP_LEFT -BX_KEY_KP_MULTIPLY none SDLK_KP_MULTIPLY -BX_KEY_KP_PAGE_DOWN none SDLK_KP3 -#BX_KEY_KP_PAGE_DOWN none SDLK_KP_PAGE_DOWN -BX_KEY_KP_PAGE_UP none SDLK_KP9 -#BX_KEY_KP_PAGE_UP none SDLK_KP_PAGE_UP -BX_KEY_KP_RIGHT none SDLK_KP6 -#BX_KEY_KP_RIGHT none SDLK_KP_Right -BX_KEY_KP_SUBTRACT none SDLK_KP_MINUS -BX_KEY_KP_UP none SDLK_KP8 -#BX_KEY_KP_UP none SDLK_KP_Up -BX_KEY_LEFT none SDLK_LEFT -#BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L '{' SDLK_BRACELEFT -BX_KEY_LEFT_BRACKET '[' SDLK_LEFTBRACKET -BX_KEY_MENU none SDLK_MENU -BX_KEY_MINUS '-' SDLK_MINUS -BX_KEY_MINUS+BX_KEY_SHIFT_L '_' SDLK_UNDERSCORE -BX_KEY_NUM_LOCK none SDLK_NUMLOCK -BX_KEY_PAGE_DOWN none SDLK_PAGEDOWN -BX_KEY_PAGE_UP none SDLK_PAGEUP -BX_KEY_PAUSE none SDLK_BREAK -BX_KEY_PAUSE none SDLK_PAUSE -BX_KEY_PERIOD+BX_KEY_SHIFT_L '>' SDLK_GREATER -BX_KEY_PERIOD '.' SDLK_PERIOD -BX_KEY_PRINT none SDLK_PRINT -BX_KEY_PRINT none SDLK_SYSREQ -BX_KEY_RIGHT none SDLK_RIGHT -#BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '}' SDLK_BRACERIGHT -BX_KEY_RIGHT_BRACKET ']' SDLK_RIGHTBRACKET -BX_KEY_SCRL_LOCK none SDLK_SCROLLOCK -BX_KEY_SEMICOLON+BX_KEY_SHIFT_L ':' SDLK_COLON -BX_KEY_SEMICOLON ';' SDLK_SEMICOLON -BX_KEY_SHIFT_L none SDLK_LSHIFT -BX_KEY_SHIFT_R none SDLK_RSHIFT -BX_KEY_SINGLE_QUOTE apostrophe SDLK_QUOTE -BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L '"' SDLK_QUOTEDBL -BX_KEY_SLASH+BX_KEY_SHIFT_L '?' SDLK_QUESTION -BX_KEY_SLASH '/' SDLK_SLASH -BX_KEY_SPACE space SDLK_SPACE -#BX_KEY_TAB none SDLK_ISO_LEFT_TAB -BX_KEY_TAB tab SDLK_TAB -BX_KEY_UP none SDLK_UP -BX_KEY_WIN_L none SDLK_LSUPER -BX_KEY_WIN_R none SDLK_LSUPER diff --git a/tools/ioemu/gui/keymaps/x11-pc-be.map b/tools/ioemu/gui/keymaps/x11-pc-be.map deleted file mode 100644 index 0a607e00c5..0000000000 --- a/tools/ioemu/gui/keymaps/x11-pc-be.map +++ /dev/null @@ -1,220 +0,0 @@ -# Bochs Keymap file -# $Id: x11-pc-be.map,v 1.2 2003/07/29 13:31:11 bdenney Exp $ -# Target: PC(x86) keyboard, BE keymap -# Author: Wouter Verhelst, -# based on FR keymap by Christophe Bothamy, Bryce Denney -# -# The keymap file describes the layout of a keyboard, and how it translates -# into Bochs key codes. -# -# Format: -# BX_Keysym ASCII_equivalent Xwin_Keysym -# -# Or, for keys that require modifiers: -# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym -# -# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in -# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it -# could be any key. Presently a maximum of one modifier is supported, but this -# could be changed in keymap.h (structure def has only one slot for modifier), -# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1 -# modifier). -# -# The ASCII_equivalent must be either apostrophe + one character + apostrophe, -# or one of these keywords: space, return, tab, backslash, apostrophe, none. -# This format is designed to look like a char constant in C, but it's a very -# simple parser. There's no concept of backslash being an escape char. The -# backslash and apostrophe entries are provided for aesthetic purposes only: no -# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are -# ugly. -# -# Xwin_Keysym is the X windows equivalent of the key combination. These -# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h. -# If you're running X windows, Bochs will take each of these Xwin_Keysyms, -# pull off the XK_ in front, and use XStringToKeysym() to change them into -# numerical codes. If this lookup fails, you will get a panic and you need -# to edit the keymap file. - -BX_KEY_0+BX_KEY_SHIFT_L '0' XK_0 -BX_KEY_0 'à' XK_agrave -BX_KEY_0+BX_KEY_ALT_R '}' XK_braceright -BX_KEY_1+BX_KEY_SHIFT_L '1' XK_1 -BX_KEY_1 '&' XK_ampersand -BX_KEY_1+BX_KEY_ALT_R '|' XK_bar -BX_KEY_2+BX_KEY_SHIFT_L '2' XK_2 -BX_KEY_2+BX_KEY_ALT_R '@' XK_at -BX_KEY_2 'é' XK_eacute -BX_KEY_3+BX_KEY_SHIFT_L '3' XK_3 -BX_KEY_3+BX_KEY_ALT_R '#' XK_numbersign -BX_KEY_3 '"' XK_quotedbl -BX_KEY_4+BX_KEY_SHIFT_L '4' XK_4 -BX_KEY_4 apostrophe XK_apostrophe -BX_KEY_5+BX_KEY_SHIFT_L '5' XK_5 -BX_KEY_5 '(' XK_parenleft -BX_KEY_6+BX_KEY_SHIFT_L '6' XK_6 -BX_KEY_6+BX_KEY_ALT_R '^' XK_asciicircum -BX_KEY_6 '§' XK_section -BX_KEY_7+BX_KEY_SHIFT_L '7' XK_7 -BX_KEY_7 'è' XK_egrave -BX_KEY_8+BX_KEY_SHIFT_L '8' XK_8 -BX_KEY_8 '!' XK_exclam -BX_KEY_9+BX_KEY_SHIFT_L '9' XK_9 -BX_KEY_9+BX_KEY_ALT_R '{' XK_braceleft -BX_KEY_9 'ç' XK_ccedilla -BX_KEY_A+BX_KEY_SHIFT_L 'Q' XK_Q -BX_KEY_A 'q' XK_q -BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B -BX_KEY_B 'b' XK_b -BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C -BX_KEY_C 'c' XK_c -BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D -BX_KEY_D 'd' XK_d -BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E -BX_KEY_E 'e' XK_e -BX_KEY_E+BX_KEY_ALT_R none XK_EuroSign -BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F -BX_KEY_F 'f' XK_f -BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G -BX_KEY_G 'g' XK_g -BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H -BX_KEY_H 'h' XK_h -BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I -BX_KEY_I 'i' XK_i -BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J -BX_KEY_J 'j' XK_j -BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K -BX_KEY_K 'k' XK_k -BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L -BX_KEY_L 'l' XK_l -BX_KEY_M+BX_KEY_SHIFT_L '?' XK_question -BX_KEY_M ',' XK_comma -BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N -BX_KEY_N 'n' XK_n -BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O -BX_KEY_O 'o' XK_o -BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P -BX_KEY_P 'p' XK_p -BX_KEY_Q+BX_KEY_SHIFT_L 'A' XK_A -BX_KEY_Q 'a' XK_a -BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R -BX_KEY_R 'r' XK_r -BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S -BX_KEY_S 's' XK_s -BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T -BX_KEY_T 't' XK_t -BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U -BX_KEY_U 'u' XK_u -BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V -BX_KEY_V 'v' XK_v -BX_KEY_W+BX_KEY_SHIFT_L 'Z' XK_Z -BX_KEY_W 'z' XK_z -BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X -BX_KEY_X 'x' XK_x -BX_KEY_Y+BX_KEY_SHIFT_L 'Y' XK_Y -BX_KEY_Y 'y' XK_y -BX_KEY_Z+BX_KEY_SHIFT_L 'W' XK_W -BX_KEY_Z 'w' XK_w -BX_KEY_F1 none XK_F1 -BX_KEY_F2 none XK_F2 -BX_KEY_F3 none XK_F3 -BX_KEY_F4 none XK_F4 -BX_KEY_F5 none XK_F5 -BX_KEY_F6 none XK_F6 -BX_KEY_F7 none XK_F7 -BX_KEY_F8 none XK_F8 -BX_KEY_F9 none XK_F9 -BX_KEY_F10 none XK_F10 -BX_KEY_F11 none XK_F11 -BX_KEY_F12 none XK_F12 -BX_KEY_ALT_L none XK_Alt_L -BX_KEY_ALT_L none XK_Meta_L -BX_KEY_ALT_R none XK_Alt_R -BX_KEY_ALT_R none XK_Mode_switch -BX_KEY_ALT_R none XK_Multi_key -BX_KEY_BACKSLASH 'µ' XK_mu -BX_KEY_BACKSLASH+BX_KEY_SHIFT_L '£' XK_sterling -BX_KEY_BACKSLASH+BX_KEY_ALT_R '`' XK_dead_grave -BX_KEY_BACKSPACE none XK_BackSpace -BX_KEY_CAPS_LOCK none XK_Caps_Lock -BX_KEY_COMMA+BX_KEY_SHIFT_L '.' XK_period -BX_KEY_COMMA ';' XK_semicolon -BX_KEY_CTRL_L none XK_Control_L -BX_KEY_CTRL_R none XK_Control_R -BX_KEY_DELETE none XK_Delete -BX_KEY_DOWN none XK_Down -BX_KEY_END none XK_End -BX_KEY_ENTER return XK_Return -BX_KEY_EQUALS '-' XK_minus -BX_KEY_EQUALS+BX_KEY_SHIFT_L '_' XK_underscore -BX_KEY_ESC none XK_Escape -BX_KEY_GRAVE '²' XK_twosuperior -BX_KEY_GRAVE+BX_KEY_SHIFT_L '³' XK_threesuperior -BX_KEY_HOME none XK_Home -BX_KEY_INSERT none XK_Insert -BX_KEY_KP_5 none XK_KP_5 -BX_KEY_KP_5 none XK_KP_Begin -BX_KEY_KP_ADD none XK_KP_Add -BX_KEY_KP_DELETE none XK_KP_Decimal -BX_KEY_KP_DELETE none XK_KP_Delete -BX_KEY_KP_DIVIDE none XK_KP_Divide -BX_KEY_KP_DOWN none XK_KP_2 -BX_KEY_KP_DOWN none XK_KP_Down -BX_KEY_KP_END none XK_KP_1 -BX_KEY_KP_END none XK_KP_End -BX_KEY_KP_ENTER none XK_KP_Enter -BX_KEY_KP_HOME none XK_KP_7 -BX_KEY_KP_HOME none XK_KP_Home -BX_KEY_KP_INSERT none XK_KP_0 -BX_KEY_KP_INSERT none XK_KP_Insert -BX_KEY_KP_LEFT none XK_KP_4 -BX_KEY_KP_LEFT none XK_KP_Left -BX_KEY_KP_MULTIPLY none XK_KP_Multiply -BX_KEY_KP_PAGE_DOWN none XK_KP_3 -BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down -BX_KEY_KP_PAGE_UP none XK_KP_9 -BX_KEY_KP_PAGE_UP none XK_KP_Page_Up -BX_KEY_KP_RIGHT none XK_KP_6 -BX_KEY_KP_RIGHT none XK_KP_Right -BX_KEY_KP_SUBTRACT none XK_KP_Subtract -BX_KEY_KP_UP none XK_KP_8 -BX_KEY_KP_UP none XK_KP_Up -BX_KEY_LEFT none XK_Left -BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '>' XK_greater -BX_KEY_LEFT_BACKSLASH '<' XK_less -BX_KEY_LEFT_BACKSLASH+BX_KEY_ALT_R backslash XK_backslash -BX_KEY_LEFT_BRACKET none XK_dead_circumflex -BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L none XK_dead_diaeresis -BX_KEY_LEFT_BRACKET+BX_KEY_ALT_R '[' XK_bracketleft -BX_KEY_MENU none XK_Menu -BX_KEY_MINUS+BX_KEY_SHIFT_L '°' XK_degree -BX_KEY_MINUS ')' XK_parenright -BX_KEY_NUM_LOCK none XK_Num_Lock -BX_KEY_PAGE_DOWN none XK_Page_Down -BX_KEY_PAGE_UP none XK_Page_Up -BX_KEY_PAUSE none XK_Break -BX_KEY_PAUSE none XK_Pause -BX_KEY_PERIOD ':' XK_colon -BX_KEY_PERIOD+BX_KEY_SHIFT_L '/' XK_slash -BX_KEY_PRINT none XK_Print -BX_KEY_PRINT none XK_Sys_Req -BX_KEY_RIGHT none XK_Right -BX_KEY_RIGHT_BRACKET '$' XK_dollar -BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '*' XK_asterisk -BX_KEY_RIGHT_BRACKET+BX_KEY_ALT_R ']' XK_bracketright -BX_KEY_SCRL_LOCK none XK_Scroll_Lock -BX_KEY_SEMICOLON+BX_KEY_SHIFT_L 'M' XK_M -BX_KEY_SEMICOLON 'm' XK_m -BX_KEY_SHIFT_L none XK_Shift_L -BX_KEY_SHIFT_R none XK_Shift_R -BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L '%' XK_percent -BX_KEY_SINGLE_QUOTE+BX_KEY_ALT_R none XK_dead_acute -BX_KEY_SINGLE_QUOTE 'ù' XK_ugrave -BX_KEY_SLASH '=' XK_equal -BX_KEY_SLASH+BX_KEY_SHIFT_L '+' XK_plus -BX_KEY_SLASH+BX_KEY_ALT_R none XK_dead_tilde -BX_KEY_SPACE space XK_space -BX_KEY_TAB none XK_ISO_Left_Tab -BX_KEY_TAB tab XK_Tab -BX_KEY_UP none XK_Up -BX_KEY_WIN_L none XK_Super_L -BX_KEY_WIN_R none XK_Super_R diff --git a/tools/ioemu/gui/keymaps/x11-pc-da.map b/tools/ioemu/gui/keymaps/x11-pc-da.map deleted file mode 100644 index 41ead2b63d..0000000000 --- a/tools/ioemu/gui/keymaps/x11-pc-da.map +++ /dev/null @@ -1,247 +0,0 @@ -# Bochs Keymap file -# $Id: x11-pc-da.map,v 0.9 2002/09/02 -# Target: PC(x86) keyboard, DA keymap -# Author: Andreas Ott -# -# The keymap file describes the layout of a keyboard, and how it translates -# into Bochs key codes. -# -# Format: -# BX_Keysym ASCII_equivalent Xwin_Keysym -# -# Or, for keys that require modifiers: -# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym -# -# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in -# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it -# could be any key. Presently a maximum of one modifier is supported, but this -# could be changed in keymap.h (structure def has only one slot for modifier), -# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1 -# modifier). -# -# The ASCII_equivalent must be either apostrophe + one character + apostrophe, -# or one of these keywords: space, return, tab, backslash, apostrophe, none. -# This format is designed to look like a char constant in C, but it's a very -# simple parser. There's no concept of backslash being an escape char. The -# backslash and apostrophe entries are provided for aesthetic purposes only: no -# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are -# ugly. -# -# Xwin_Keysym is the X windows equivalent of the key combination. These -# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h. -# If you're running X windows, Bochs will take each of these Xwin_Keysyms, -# pull off the XK_ in front, and use XStringToKeysym() to change them into -# numerical codes. If this lookup fails, you will get a panic and you need -# to edit the keymap file. - -BX_KEY_0 '0' XK_0 -BX_KEY_0+BX_KEY_ALT_R '}' XK_braceright -BX_KEY_0+BX_KEY_SHIFT_L '=' XK_equal -BX_KEY_1 '1' XK_1 -BX_KEY_1+BX_KEY_SHIFT_L '!' XK_exclam -BX_KEY_1+BX_KEY_ALT_R '¡' XK_exclamdown -BX_KEY_2 '2' XK_2 -BX_KEY_2+BX_KEY_SHIFT_L '=' XK_quotedbl -BX_KEY_2+BX_KEY_ALT_R '@' XK_at # XK_twosuperior -BX_KEY_3 '3' XK_3 -BX_KEY_3+BX_KEY_SHIFT_L '#' XK_numbersign -BX_KEY_3+BX_KEY_ALT_R '£' XK_sterling -BX_KEY_4 '4' XK_4 -BX_KEY_4+BX_KEY_SHIFT_L '¤' XK_currency -BX_KEY_4+BX_KEY_ALT_R '$' XK_dollar -BX_KEY_5 '5' XK_5 -BX_KEY_5+BX_KEY_ALT_R '½' XK_onehalf -BX_KEY_5+BX_KEY_SHIFT_L '%' XK_percent -BX_KEY_6 '6' XK_6 -BX_KEY_6+BX_KEY_SHIFT_L '&' XK_ampersand -BX_KEY_6+BX_KEY_ALT_R '¥' XK_yen -BX_KEY_7 '7' XK_7 -BX_KEY_7+BX_KEY_ALT_R '{' XK_braceleft -BX_KEY_7+BX_KEY_SHIFT_L '/' XK_slash -BX_KEY_8 '8' XK_8 -BX_KEY_8+BX_KEY_ALT_R '[' XK_bracketleft -BX_KEY_8+BX_KEY_SHIFT_L '(' XK_parenleft -BX_KEY_9 '9' XK_9 -BX_KEY_9+BX_KEY_ALT_R ']' XK_bracketright -BX_KEY_9+BX_KEY_SHIFT_L ')' XK_parenright -BX_KEY_A+BX_KEY_SHIFT_L 'A' XK_A -BX_KEY_A 'a' XK_a -BX_KEY_A+BX_KEY_ALT_R 'ª' XK_ordfeminine -BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B -BX_KEY_B 'b' XK_b -BX_KEY_B+BX_KEY_ALT_R none XK_rightdoublequotemark -BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C -BX_KEY_C 'c' XK_c -BX_KEY_C+BX_KEY_ALT_R '©' XK_copyright -BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D -BX_KEY_D 'd' XK_d -BX_KEY_D+BX_KEY_ALT_R 'ð' XK_eth -BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E -BX_KEY_E+BX_KEY_ALT_R '?' XK_EuroSign -BX_KEY_E 'e' XK_e -BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F -BX_KEY_F+BX_KEY_ALT_R '?' XK_dstroke -BX_KEY_F 'f' XK_f -BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G -BX_KEY_G+BX_KEY_ALT_R '?' XK_eng -BX_KEY_G 'g' XK_g -BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H -BX_KEY_H 'h' XK_h -BX_KEY_H+BX_KEY_ALT_R '?' XK_hstroke -BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I -BX_KEY_I 'i' XK_i -BX_KEY_I+BX_KEY_ALT_R none XK_rightarrow -BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J -BX_KEY_J 'j' XK_j -BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K -BX_KEY_K 'k' XK_k -BX_KEY_K+BX_KEY_ALT_R none XK_kra -BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L -BX_KEY_L 'l' XK_l -BX_KEY_M+BX_KEY_SHIFT_L 'M' XK_M -BX_KEY_M 'm' XK_m -BX_KEY_M+BX_KEY_ALT_R 'µ' XK_mu -BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N -BX_KEY_N 'n' XK_n -BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O -BX_KEY_O 'o' XK_o -BX_KEY_O+BX_KEY_ALT_R none XK_oslash -BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P -BX_KEY_P 'p' XK_p -BX_KEY_P+BX_KEY_ALT_R 'þ' XK_thorn -BX_KEY_Q+BX_KEY_SHIFT_L 'Q' XK_Q -BX_KEY_Q+BX_KEY_ALT_R '@' XK_at -BX_KEY_Q 'q' XK_q -BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R -BX_KEY_R+BX_KEY_ALT_R '®' XK_registered -BX_KEY_R 'r' XK_r -BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S -BX_KEY_S 's' XK_s -BX_KEY_S+BX_KEY_ALT_R 'ß' XK_ssharp -BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T -BX_KEY_T 't' XK_t -BX_KEY_T+BX_KEY_ALT_R 'þ' XK_thorn -BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U -BX_KEY_U+BX_KEY_ALT_R none XK_downarrow -BX_KEY_U 'u' XK_u -BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V -BX_KEY_V+BX_KEY_ALT_R none XK_leftdoublequotemark -BX_KEY_V 'v' XK_v -BX_KEY_W+BX_KEY_SHIFT_L 'W' XK_W -BX_KEY_W+BX_KEY_ALT_R '?' XK_lstroke -BX_KEY_W 'w' XK_w -BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X -BX_KEY_X+BX_KEY_ALT_R '»' XK_guillemotright -BX_KEY_X 'x' XK_x -BX_KEY_Y+BX_KEY_SHIFT_L 'Y' XK_Y -BX_KEY_Y+BX_KEY_ALT_R none XK_leftarrow -BX_KEY_Y 'y' XK_y -BX_KEY_Z+BX_KEY_SHIFT_L 'Z' XK_Z -BX_KEY_Z+BX_KEY_ALT_R '«' XK_guillemotleft -BX_KEY_Z 'z' XK_z -BX_KEY_F1 none XK_F1 -BX_KEY_F2 none XK_F2 -BX_KEY_F3 none XK_F3 -BX_KEY_F4 none XK_F4 -BX_KEY_F5 none XK_F5 -BX_KEY_F6 none XK_F6 -BX_KEY_F7 none XK_F7 -BX_KEY_F8 none XK_F8 -BX_KEY_F9 none XK_F9 -BX_KEY_F10 none XK_F10 -BX_KEY_F11 none XK_F11 -BX_KEY_F12 none XK_F12 -BX_KEY_ALT_L none XK_Alt_L -BX_KEY_ALT_L none XK_Meta_L -BX_KEY_ALT_R none XK_Mode_switch -BX_KEY_ALT_R none XK_Multi_key -BX_KEY_BACKSLASH apostrophe XK_apostrophe -BX_KEY_BACKSLASH+BX_KEY_SHIFT_L '*' XK_asterisk -BX_KEY_BACKSPACE none XK_BackSpace -BX_KEY_CAPS_LOCK none XK_Caps_Lock -BX_KEY_COMMA ',' XK_comma -BX_KEY_COMMA+BX_KEY_ALT_R none XK_horizconnector -BX_KEY_COMMA+BX_KEY_SHIFT_L ';' XK_semicolon -BX_KEY_CTRL_L none XK_Control_L -BX_KEY_CTRL_R none XK_Control_R -BX_KEY_DELETE none XK_Delete -BX_KEY_DOWN none XK_Down -BX_KEY_END none XK_End -BX_KEY_ENTER return XK_Return -BX_KEY_EQUALS none XK_acute -BX_KEY_EQUALS+BX_KEY_ALT_R '|' XK_bar -BX_KEY_EQUALS+BX_KEY_SHIFT_L '`' XK_grave -BX_KEY_ESC none XK_Escape -BX_KEY_GRAVE '½' XK_onehalf -BX_KEY_GRAVE+BX_KEY_SHIFT_L '§' XK_section -BX_KEY_GRAVE+BX_KEY_ALT_R '¾' XK_threequarters -BX_KEY_HOME none XK_Home -BX_KEY_INSERT none XK_Insert -BX_KEY_KP_5 none XK_KP_5 -BX_KEY_KP_5 none XK_KP_Begin -BX_KEY_KP_ADD none XK_KP_Add -BX_KEY_KP_DELETE none XK_KP_Decimal -BX_KEY_KP_DELETE none XK_KP_Delete -BX_KEY_KP_DIVIDE none XK_KP_Divide -BX_KEY_KP_DOWN none XK_KP_2 -BX_KEY_KP_DOWN none XK_KP_Down -BX_KEY_KP_END none XK_KP_1 -BX_KEY_KP_END none XK_KP_End -BX_KEY_KP_ENTER none XK_KP_Enter -BX_KEY_KP_HOME none XK_KP_7 -BX_KEY_KP_HOME none XK_KP_Home -BX_KEY_KP_INSERT none XK_KP_0 -BX_KEY_KP_INSERT none XK_KP_Insert -BX_KEY_KP_LEFT none XK_KP_4 -BX_KEY_KP_LEFT none XK_KP_Left -BX_KEY_KP_MULTIPLY none XK_KP_Multiply -BX_KEY_KP_PAGE_DOWN none XK_KP_3 -BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down -BX_KEY_KP_PAGE_UP none XK_KP_9 -BX_KEY_KP_PAGE_UP none XK_KP_Page_Up -BX_KEY_KP_RIGHT none XK_KP_6 -BX_KEY_KP_RIGHT none XK_KP_Right -BX_KEY_KP_SUBTRACT none XK_KP_Subtract -BX_KEY_KP_UP none XK_KP_8 -BX_KEY_KP_UP none XK_KP_Up -BX_KEY_LEFT none XK_Left -BX_KEY_LEFT_BACKSLASH+BX_KEY_ALT_R backslash XK_backslash -BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '>' XK_greater -BX_KEY_LEFT_BACKSLASH '<' XK_less -BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L 'Å' XK_Aring -BX_KEY_LEFT_BRACKET+BX_KEY_ALT_L none XK_diaeresis -BX_KEY_LEFT_BRACKET 'å' XK_aring -BX_KEY_MENU none XK_Menu -BX_KEY_MINUS+BX_KEY_ALT_R '±' XK_plusminus -BX_KEY_MINUS+BX_KEY_SHIFT_L '?' XK_question -BX_KEY_MINUS '+' XK_plus -BX_KEY_NUM_LOCK none XK_Num_Lock -BX_KEY_PAGE_DOWN none XK_Page_Down -BX_KEY_PAGE_UP none XK_Page_Up -BX_KEY_PAUSE none XK_Break -BX_KEY_PAUSE none XK_Pause -BX_KEY_PERIOD+BX_KEY_SHIFT_L ':' XK_colon -BX_KEY_PERIOD '.' XK_period -BX_KEY_PERIOD+BX_KEY_ALT_R '·' XK_periodcentered -BX_KEY_PRINT none XK_Print -BX_KEY_PRINT none XK_Sys_Req -BX_KEY_RIGHT none XK_Right -BX_KEY_RIGHT_BRACKET+BX_KEY_ALT_R '~' XK_asciitilde -BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '^' XK_asciicircum -BX_KEY_RIGHT_BRACKET '"' XK_diaeresis -BX_KEY_SCRL_LOCK none XK_Scroll_Lock -BX_KEY_SEMICOLON+BX_KEY_SHIFT_L 'Æ' XK_AE -BX_KEY_SEMICOLON 'æ' XK_ae -BX_KEY_SHIFT_L none XK_Shift_L -BX_KEY_SHIFT_R none XK_Shift_R -BX_KEY_SINGLE_QUOTE 'ø' XK_oslash -BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L 'Ø' XK_Ooblique -BX_KEY_SLASH+BX_KEY_ALT_R '­' XK_hyphen -BX_KEY_SLASH '-' XK_minus -BX_KEY_SLASH+BX_KEY_SHIFT_L '_' XK_underscore -BX_KEY_SPACE space XK_space -BX_KEY_TAB none XK_ISO_Left_Tab -BX_KEY_TAB tab XK_Tab -BX_KEY_UP none XK_Up -BX_KEY_WIN_L none XK_Super_L -BX_KEY_WIN_R none XK_Super_R diff --git a/tools/ioemu/gui/keymaps/x11-pc-de.map b/tools/ioemu/gui/keymaps/x11-pc-de.map deleted file mode 100644 index 929ad0625e..0000000000 --- a/tools/ioemu/gui/keymaps/x11-pc-de.map +++ /dev/null @@ -1,247 +0,0 @@ -# Bochs Keymap file -# $Id: x11-pc-de.map,v 1.7 2002/10/24 21:06:56 bdenney Exp $ -# Target: PC(x86) keyboard, DE keymap -# Author: Volker Ruppert -# -# The keymap file describes the layout of a keyboard, and how it translates -# into Bochs key codes. -# -# Format: -# BX_Keysym ASCII_equivalent Xwin_Keysym -# -# Or, for keys that require modifiers: -# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym -# -# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in -# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it -# could be any key. Presently a maximum of one modifier is supported, but this -# could be changed in keymap.h (structure def has only one slot for modifier), -# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1 -# modifier). -# -# The ASCII_equivalent must be either apostrophe + one character + apostrophe, -# or one of these keywords: space, return, tab, backslash, apostrophe, none. -# This format is designed to look like a char constant in C, but it's a very -# simple parser. There's no concept of backslash being an escape char. The -# backslash and apostrophe entries are provided for aesthetic purposes only: no -# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are -# ugly. -# -# Xwin_Keysym is the X windows equivalent of the key combination. These -# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h. -# If you're running X windows, Bochs will take each of these Xwin_Keysyms, -# pull off the XK_ in front, and use XStringToKeysym() to change them into -# numerical codes. If this lookup fails, you will get a panic and you need -# to edit the keymap file. - -BX_KEY_0 '0' XK_0 -BX_KEY_0+BX_KEY_ALT_R '}' XK_braceright -BX_KEY_0+BX_KEY_SHIFT_L '=' XK_equal -BX_KEY_1 '1' XK_1 -BX_KEY_1+BX_KEY_SHIFT_L '!' XK_exclam -BX_KEY_1+BX_KEY_ALT_R '¹' XK_onesuperior -BX_KEY_2 '2' XK_2 -BX_KEY_2+BX_KEY_SHIFT_L '"' XK_quotedbl -BX_KEY_2+BX_KEY_ALT_R '²' XK_twosuperior -BX_KEY_3 '3' XK_3 -BX_KEY_3+BX_KEY_SHIFT_L '§' XK_section -BX_KEY_3+BX_KEY_ALT_R '³' XK_threesuperior -BX_KEY_4 '4' XK_4 -BX_KEY_4+BX_KEY_SHIFT_L '$' XK_dollar -BX_KEY_4+BX_KEY_ALT_R '¼' XK_onequarter -BX_KEY_5 '5' XK_5 -BX_KEY_5+BX_KEY_ALT_R '½' XK_onehalf -BX_KEY_5+BX_KEY_SHIFT_L '%' XK_percent -BX_KEY_6 '6' XK_6 -BX_KEY_6+BX_KEY_SHIFT_L '&' XK_ampersand -BX_KEY_6+BX_KEY_ALT_R '¾' XK_threequarters -BX_KEY_7 '7' XK_7 -BX_KEY_7+BX_KEY_ALT_R '{' XK_braceleft -BX_KEY_7+BX_KEY_SHIFT_L '/' XK_slash -BX_KEY_8 '8' XK_8 -BX_KEY_8+BX_KEY_ALT_R '[' XK_bracketleft -BX_KEY_8+BX_KEY_SHIFT_L '(' XK_parenleft -BX_KEY_9 '9' XK_9 -BX_KEY_9+BX_KEY_ALT_R ']' XK_bracketright -BX_KEY_9+BX_KEY_SHIFT_L ')' XK_parenright -BX_KEY_A+BX_KEY_SHIFT_L 'A' XK_A -BX_KEY_A 'a' XK_a -BX_KEY_A+BX_KEY_ALT_R 'æ' XK_ae -BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B -BX_KEY_B 'b' XK_b -BX_KEY_B+BX_KEY_ALT_R none XK_rightdoublequotemark -BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C -BX_KEY_C 'c' XK_c -BX_KEY_C+BX_KEY_ALT_R '¢' XK_cent -BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D -BX_KEY_D 'd' XK_d -BX_KEY_D+BX_KEY_ALT_R 'ð' XK_eth -BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E -BX_KEY_E+BX_KEY_ALT_R none XK_EuroSign -BX_KEY_E 'e' XK_e -BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F -BX_KEY_F+BX_KEY_ALT_R none XK_dstroke -BX_KEY_F 'f' XK_f -BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G -BX_KEY_G+BX_KEY_ALT_R none XK_eng -BX_KEY_G 'g' XK_g -BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H -BX_KEY_H 'h' XK_h -BX_KEY_H+BX_KEY_ALT_R none XK_hstroke -BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I -BX_KEY_I 'i' XK_i -BX_KEY_I+BX_KEY_ALT_R none XK_rightarrow -BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J -BX_KEY_J 'j' XK_j -BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K -BX_KEY_K 'k' XK_k -BX_KEY_K+BX_KEY_ALT_R none XK_kra -BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L -BX_KEY_L 'l' XK_l -BX_KEY_M+BX_KEY_SHIFT_L 'M' XK_M -BX_KEY_M 'm' XK_m -BX_KEY_M+BX_KEY_ALT_R 'µ' XK_mu -BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N -BX_KEY_N 'n' XK_n -BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O -BX_KEY_O 'o' XK_o -BX_KEY_O+BX_KEY_ALT_R 'ø' XK_oslash -BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P -BX_KEY_P 'p' XK_p -BX_KEY_P+BX_KEY_ALT_R 'þ' XK_thorn -BX_KEY_Q+BX_KEY_SHIFT_L 'Q' XK_Q -BX_KEY_Q+BX_KEY_ALT_R '@' XK_at -BX_KEY_Q 'q' XK_q -BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R -BX_KEY_R+BX_KEY_ALT_R '¶' XK_paragraph -BX_KEY_R 'r' XK_r -BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S -BX_KEY_S 's' XK_s -BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T -BX_KEY_T 't' XK_t -BX_KEY_T+BX_KEY_ALT_R none XK_tslash -BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U -BX_KEY_U+BX_KEY_ALT_R none XK_downarrow -BX_KEY_U 'u' XK_u -BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V -BX_KEY_V+BX_KEY_ALT_R none XK_leftdoublequotemark -BX_KEY_V 'v' XK_v -BX_KEY_W+BX_KEY_SHIFT_L 'W' XK_W -BX_KEY_W+BX_KEY_ALT_R none XK_lstroke -BX_KEY_W 'w' XK_w -BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X -BX_KEY_X+BX_KEY_ALT_R '»' XK_guillemotright -BX_KEY_X 'x' XK_x -BX_KEY_Y+BX_KEY_SHIFT_L 'Z' XK_Z -BX_KEY_Y+BX_KEY_ALT_R none XK_leftarrow -BX_KEY_Y 'z' XK_z -BX_KEY_Z+BX_KEY_SHIFT_L 'Y' XK_Y -BX_KEY_Z+BX_KEY_ALT_R '«' XK_guillemotleft -BX_KEY_Z 'y' XK_y -BX_KEY_F1 none XK_F1 -BX_KEY_F2 none XK_F2 -BX_KEY_F3 none XK_F3 -BX_KEY_F4 none XK_F4 -BX_KEY_F5 none XK_F5 -BX_KEY_F6 none XK_F6 -BX_KEY_F7 none XK_F7 -BX_KEY_F8 none XK_F8 -BX_KEY_F9 none XK_F9 -BX_KEY_F10 none XK_F10 -BX_KEY_F11 none XK_F11 -BX_KEY_F12 none XK_F12 -BX_KEY_ALT_L none XK_Alt_L -BX_KEY_ALT_L none XK_Meta_L -BX_KEY_ALT_R none XK_Alt_R -BX_KEY_ALT_R none XK_Mode_switch -BX_KEY_ALT_R none XK_Multi_key -BX_KEY_BACKSLASH apostrophe XK_apostrophe -BX_KEY_BACKSLASH '#' XK_numbersign -BX_KEY_BACKSPACE none XK_BackSpace -BX_KEY_CAPS_LOCK none XK_Caps_Lock -BX_KEY_COMMA ',' XK_comma -BX_KEY_COMMA+BX_KEY_ALT_R none XK_horizconnector -BX_KEY_COMMA+BX_KEY_SHIFT_L ';' XK_semicolon -BX_KEY_CTRL_L none XK_Control_L -BX_KEY_CTRL_R none XK_Control_R -BX_KEY_DELETE none XK_Delete -BX_KEY_DOWN none XK_Down -BX_KEY_END none XK_End -BX_KEY_ENTER return XK_Return -BX_KEY_EQUALS none XK_acute -BX_KEY_EQUALS+BX_KEY_ALT_R '¸' XK_cedilla -BX_KEY_EQUALS+BX_KEY_SHIFT_L '`' XK_grave -BX_KEY_ESC none XK_Escape -BX_KEY_GRAVE '^' XK_asciicircum -BX_KEY_GRAVE+BX_KEY_SHIFT_L '°' XK_degree -BX_KEY_GRAVE+BX_KEY_ALT_R '¬' XK_notsign -BX_KEY_HOME none XK_Home -BX_KEY_INSERT none XK_Insert -BX_KEY_KP_5 none XK_KP_5 -BX_KEY_KP_5 none XK_KP_Begin -BX_KEY_KP_ADD none XK_KP_Add -BX_KEY_KP_DELETE none XK_KP_Decimal -BX_KEY_KP_DELETE none XK_KP_Delete -BX_KEY_KP_DIVIDE none XK_KP_Divide -BX_KEY_KP_DOWN none XK_KP_2 -BX_KEY_KP_DOWN none XK_KP_Down -BX_KEY_KP_END none XK_KP_1 -BX_KEY_KP_END none XK_KP_End -BX_KEY_KP_ENTER none XK_KP_Enter -BX_KEY_KP_HOME none XK_KP_7 -BX_KEY_KP_HOME none XK_KP_Home -BX_KEY_KP_INSERT none XK_KP_0 -BX_KEY_KP_INSERT none XK_KP_Insert -BX_KEY_KP_LEFT none XK_KP_4 -BX_KEY_KP_LEFT none XK_KP_Left -BX_KEY_KP_MULTIPLY none XK_KP_Multiply -BX_KEY_KP_PAGE_DOWN none XK_KP_3 -BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down -BX_KEY_KP_PAGE_UP none XK_KP_9 -BX_KEY_KP_PAGE_UP none XK_KP_Page_Up -BX_KEY_KP_RIGHT none XK_KP_6 -BX_KEY_KP_RIGHT none XK_KP_Right -BX_KEY_KP_SUBTRACT none XK_KP_Subtract -BX_KEY_KP_UP none XK_KP_8 -BX_KEY_KP_UP none XK_KP_Up -BX_KEY_LEFT none XK_Left -BX_KEY_LEFT_BACKSLASH+BX_KEY_ALT_R '|' XK_bar -BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '>' XK_greater -BX_KEY_LEFT_BACKSLASH '<' XK_less -BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L 'Ü' XK_Udiaeresis -BX_KEY_LEFT_BRACKET+BX_KEY_ALT_L none XK_diaeresis -BX_KEY_LEFT_BRACKET 'ü' XK_udiaeresis -BX_KEY_MENU none XK_Menu -BX_KEY_MINUS+BX_KEY_ALT_L backslash XK_backslash -BX_KEY_MINUS+BX_KEY_SHIFT_L '?' XK_question -BX_KEY_MINUS 'ß' XK_ssharp -BX_KEY_NUM_LOCK none XK_Num_Lock -BX_KEY_PAGE_DOWN none XK_Page_Down -BX_KEY_PAGE_UP none XK_Page_Up -BX_KEY_PAUSE none XK_Break -BX_KEY_PAUSE none XK_Pause -BX_KEY_PERIOD+BX_KEY_SHIFT_L ':' XK_colon -BX_KEY_PERIOD '.' XK_period -BX_KEY_PERIOD+BX_KEY_ALT_L '·' XK_periodcentered -BX_KEY_PRINT none XK_Print -BX_KEY_PRINT none XK_Sys_Req -BX_KEY_RIGHT none XK_Right -BX_KEY_RIGHT_BRACKET+BX_KEY_ALT_R '~' XK_asciitilde -BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '*' XK_asterisk -BX_KEY_RIGHT_BRACKET '+' XK_plus -BX_KEY_SCRL_LOCK none XK_Scroll_Lock -BX_KEY_SEMICOLON+BX_KEY_SHIFT_L 'Ö' XK_Odiaeresis -BX_KEY_SEMICOLON 'ö' XK_odiaeresis -BX_KEY_SHIFT_L none XK_Shift_L -BX_KEY_SHIFT_R none XK_Shift_R -BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L 'Ä' XK_Adiaeresis -BX_KEY_SINGLE_QUOTE 'ä' XK_adiaeresis -BX_KEY_SLASH none XK_dead_belowdot -BX_KEY_SLASH '-' XK_minus -BX_KEY_SLASH+BX_KEY_SHIFT_L '_' XK_underscore -BX_KEY_SPACE space XK_space -BX_KEY_TAB none XK_ISO_Left_Tab -BX_KEY_TAB tab XK_Tab -BX_KEY_UP none XK_Up -BX_KEY_WIN_L none XK_Super_L -BX_KEY_WIN_R none XK_Super_R diff --git a/tools/ioemu/gui/keymaps/x11-pc-es.map b/tools/ioemu/gui/keymaps/x11-pc-es.map deleted file mode 100644 index 3856044ac0..0000000000 --- a/tools/ioemu/gui/keymaps/x11-pc-es.map +++ /dev/null @@ -1,217 +0,0 @@ -# Bochs Keymap file -# $Id: x11-pc-es.map,v 1.4 2002/09/25 08:00:24 bdenney Exp $ -# Target: PC(x86) keyboard, ES keymap -# Author: Vicente Hernando Ara -# -# The keymap file describes the layout of a keyboard, and how it translates -# into Bochs key codes. -# -# Format: -# BX_Keysym ASCII_equivalent Xwin_Keysym -# -# Or, for keys that require modifiers: -# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym -# -# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in -# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it -# could be any key. Presently a maximum of one modifier is supported, but this -# could be changed in keymap.h (structure def has only one slot for modifier), -# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1 -# modifier). -# -# The ASCII_equivalent must be either apostrophe + one character + apostrophe, -# or one of these keywords: space, return, tab, backslash, apostrophe, none. -# This format is designed to look like a char constant in C, but it's a very -# simple parser. There's no concept of backslash being an escape char. The -# backslash and apostrophe entries are provided for aesthetic purposes only: no -# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are -# ugly. -# -# Xwin_Keysym is the X windows equivalent of the key combination. These -# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h. -# If you're running X windows, Bochs will take each of these Xwin_Keysyms, -# pull off the XK_ in front, and use XStringToKeysym() to change them into -# numerical codes. If this lookup fails, you will get a panic and you need -# to edit the keymap file. -# -BX_KEY_0 none XK_0 -BX_KEY_0 none XK_equal -BX_KEY_1 none XK_1 -BX_KEY_1 none XK_bar -BX_KEY_1 none XK_exclam -BX_KEY_2 none XK_2 -BX_KEY_2 none XK_at -BX_KEY_2 none XK_quotedbl -BX_KEY_3 none XK_3 -BX_KEY_3 none XK_numbersign -BX_KEY_3 none XK_periodcentered -BX_KEY_4 none XK_4 -BX_KEY_4 none XK_dollar -BX_KEY_5 none XK_5 -BX_KEY_5 none XK_percent -BX_KEY_6 none XK_6 -BX_KEY_6 none XK_ampersand -BX_KEY_7 none XK_7 -BX_KEY_7 none XK_slash -BX_KEY_8 none XK_8 -BX_KEY_8 none XK_parenleft -BX_KEY_9 none XK_9 -BX_KEY_9 none XK_parenright -BX_KEY_A none XK_A -BX_KEY_A none XK_a -BX_KEY_B none XK_B -BX_KEY_B none XK_b -BX_KEY_C none XK_C -BX_KEY_C none XK_c -BX_KEY_D none XK_D -BX_KEY_D none XK_d -BX_KEY_E none XK_E -BX_KEY_E none XK_EuroSign -BX_KEY_E none XK_e -BX_KEY_F none XK_F -BX_KEY_F none XK_f -BX_KEY_G none XK_G -BX_KEY_G none XK_g -BX_KEY_H none XK_H -BX_KEY_H none XK_h -BX_KEY_I none XK_I -BX_KEY_I none XK_i -BX_KEY_J none XK_J -BX_KEY_J none XK_j -BX_KEY_K none XK_K -BX_KEY_K none XK_k -BX_KEY_L none XK_L -BX_KEY_L none XK_l -BX_KEY_M none XK_M -BX_KEY_M none XK_m -BX_KEY_N none XK_N -BX_KEY_N none XK_n -BX_KEY_O none XK_O -BX_KEY_O none XK_o -BX_KEY_P none XK_P -BX_KEY_P none XK_p -BX_KEY_Q none XK_Q -BX_KEY_Q none XK_q -BX_KEY_R none XK_R -BX_KEY_R none XK_r -BX_KEY_S none XK_S -BX_KEY_S none XK_s -BX_KEY_T none XK_T -BX_KEY_T none XK_t -BX_KEY_U none XK_U -BX_KEY_U none XK_u -BX_KEY_V none XK_V -BX_KEY_V none XK_v -BX_KEY_W none XK_W -BX_KEY_W none XK_w -BX_KEY_X none XK_X -BX_KEY_X none XK_x -BX_KEY_Y none XK_Y -BX_KEY_Y none XK_y -BX_KEY_Z none XK_Z -BX_KEY_Z none XK_z -BX_KEY_F1 none XK_F1 -BX_KEY_F2 none XK_F2 -BX_KEY_F3 none XK_F3 -BX_KEY_F4 none XK_F4 -BX_KEY_F5 none XK_F5 -BX_KEY_F6 none XK_F6 -BX_KEY_F7 none XK_F7 -BX_KEY_F8 none XK_F8 -BX_KEY_F9 none XK_F9 -BX_KEY_F10 none XK_F10 -BX_KEY_F11 none XK_F11 -BX_KEY_F12 none XK_F12 -BX_KEY_ALT_L none XK_Alt_L -BX_KEY_ALT_L none XK_Meta_L -BX_KEY_ALT_R none XK_Alt_R -BX_KEY_ALT_R none XK_Mode_switch -BX_KEY_ALT_R none XK_Multi_key -BX_KEY_BACKSLASH none XK_Ccedilla -BX_KEY_BACKSLASH none XK_ccedilla -BX_KEY_BACKSPACE none XK_BackSpace -BX_KEY_CAPS_LOCK none XK_Caps_Lock -BX_KEY_COMMA none XK_comma -BX_KEY_COMMA none XK_semicolon -BX_KEY_CTRL_L none XK_Control_L -BX_KEY_CTRL_R none XK_Control_R -BX_KEY_DELETE none XK_Delete -BX_KEY_DOWN none XK_Down -BX_KEY_END none XK_End -BX_KEY_ENTER none XK_Return -BX_KEY_EQUALS none XK_exclamdown -BX_KEY_EQUALS none XK_questiondown -BX_KEY_ESC none XK_Escape -BX_KEY_GRAVE none XK_asciitilde -BX_KEY_GRAVE none XK_backslash -BX_KEY_GRAVE none XK_grave -BX_KEY_GRAVE none XK_masculine -BX_KEY_GRAVE none XK_ordfeminine -BX_KEY_HOME none XK_Home -BX_KEY_INSERT none XK_Insert -BX_KEY_KP_5 none XK_KP_5 -BX_KEY_KP_5 none XK_KP_Begin -BX_KEY_KP_ADD none XK_KP_Add -BX_KEY_KP_DELETE none XK_KP_Decimal -BX_KEY_KP_DELETE none XK_KP_Delete -BX_KEY_KP_DIVIDE none XK_KP_Divide -BX_KEY_KP_DOWN none XK_KP_2 -BX_KEY_KP_DOWN none XK_KP_Down -BX_KEY_KP_END none XK_KP_1 -BX_KEY_KP_END none XK_KP_End -BX_KEY_KP_ENTER none XK_KP_Enter -BX_KEY_KP_HOME none XK_KP_7 -BX_KEY_KP_HOME none XK_KP_Home -BX_KEY_KP_INSERT none XK_KP_0 -BX_KEY_KP_INSERT none XK_KP_Insert -BX_KEY_KP_LEFT none XK_KP_4 -BX_KEY_KP_LEFT none XK_KP_Left -BX_KEY_KP_MULTIPLY none XK_KP_Multiply -BX_KEY_KP_PAGE_DOWN none XK_KP_3 -BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down -BX_KEY_KP_PAGE_UP none XK_KP_9 -BX_KEY_KP_PAGE_UP none XK_KP_Page_Up -BX_KEY_KP_RIGHT none XK_KP_6 -BX_KEY_KP_RIGHT none XK_KP_Right -BX_KEY_KP_SUBTRACT none XK_KP_Subtract -BX_KEY_KP_UP none XK_KP_8 -BX_KEY_KP_UP none XK_KP_Up -BX_KEY_LEFT none XK_Left -BX_KEY_LEFT_BACKSLASH none XK_greater -BX_KEY_LEFT_BACKSLASH none XK_less -BX_KEY_LEFT_BRACKET none XK_braceleft -BX_KEY_LEFT_BRACKET none XK_bracketleft -BX_KEY_LEFT_BRACKET none XK_dead_circumflex -BX_KEY_LEFT_BRACKET none XK_dead_grave -BX_KEY_MENU none XK_Menu -BX_KEY_MINUS none XK_apostrophe -BX_KEY_MINUS none XK_question -BX_KEY_NUM_LOCK none XK_Num_Lock -BX_KEY_PAGE_DOWN none XK_Page_Down -BX_KEY_PAGE_UP none XK_Page_Up -BX_KEY_PAUSE none XK_Break -BX_KEY_PAUSE none XK_Pause -BX_KEY_PERIOD none XK_colon -BX_KEY_PERIOD none XK_period -BX_KEY_PRINT none XK_Print -BX_KEY_PRINT none XK_Sys_Req -BX_KEY_RIGHT none XK_Right -BX_KEY_RIGHT_BRACKET none XK_asterisk -BX_KEY_RIGHT_BRACKET none XK_braceright -BX_KEY_RIGHT_BRACKET none XK_bracketright -BX_KEY_RIGHT_BRACKET none XK_plus -BX_KEY_SCRL_LOCK none XK_Scroll_Lock -BX_KEY_SEMICOLON none XK_Ntilde -BX_KEY_SEMICOLON none XK_ntilde -BX_KEY_SHIFT_L none XK_Shift_L -BX_KEY_SHIFT_R none XK_Shift_R -BX_KEY_SINGLE_QUOTE none XK_dead_acute -BX_KEY_SINGLE_QUOTE none XK_dead_diaeresis -BX_KEY_SLASH none XK_minus -BX_KEY_SLASH none XK_underscore -BX_KEY_SPACE none XK_space -BX_KEY_TAB none XK_ISO_Left_Tab -BX_KEY_TAB none XK_Tab -BX_KEY_UP none XK_Up -BX_KEY_WIN_L none XK_Super_L -BX_KEY_WIN_R none XK_Super_R diff --git a/tools/ioemu/gui/keymaps/x11-pc-fr.map b/tools/ioemu/gui/keymaps/x11-pc-fr.map deleted file mode 100644 index 869b328552..0000000000 --- a/tools/ioemu/gui/keymaps/x11-pc-fr.map +++ /dev/null @@ -1,218 +0,0 @@ -# Bochs Keymap file -# $Id: x11-pc-fr.map,v 1.5 2002/09/25 08:00:24 bdenney Exp $ -# Target: PC(x86) keyboard, FR keymap -# Author: Christophe Bothamy, Bryce Denney -# -# The keymap file describes the layout of a keyboard, and how it translates -# into Bochs key codes. -# -# Format: -# BX_Keysym ASCII_equivalent Xwin_Keysym -# -# Or, for keys that require modifiers: -# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym -# -# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in -# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it -# could be any key. Presently a maximum of one modifier is supported, but this -# could be changed in keymap.h (structure def has only one slot for modifier), -# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1 -# modifier). -# -# The ASCII_equivalent must be either apostrophe + one character + apostrophe, -# or one of these keywords: space, return, tab, backslash, apostrophe, none. -# This format is designed to look like a char constant in C, but it's a very -# simple parser. There's no concept of backslash being an escape char. The -# backslash and apostrophe entries are provided for aesthetic purposes only: no -# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are -# ugly. -# -# Xwin_Keysym is the X windows equivalent of the key combination. These -# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h. -# If you're running X windows, Bochs will take each of these Xwin_Keysyms, -# pull off the XK_ in front, and use XStringToKeysym() to change them into -# numerical codes. If this lookup fails, you will get a panic and you need -# to edit the keymap file. - -BX_KEY_0+BX_KEY_SHIFT_L '0' XK_0 -BX_KEY_0 'à' XK_agrave -BX_KEY_0+BX_KEY_ALT_R '@' XK_at -BX_KEY_1+BX_KEY_SHIFT_L '1' XK_1 -BX_KEY_1 '&' XK_ampersand -BX_KEY_2+BX_KEY_SHIFT_L '2' XK_2 -BX_KEY_2+BX_KEY_ALT_R '~' XK_asciitilde -BX_KEY_2 'é' XK_eacute -BX_KEY_3+BX_KEY_SHIFT_L '3' XK_3 -BX_KEY_3+BX_KEY_ALT_R '#' XK_numbersign -BX_KEY_3 '"' XK_quotedbl -BX_KEY_4+BX_KEY_SHIFT_L '4' XK_4 -BX_KEY_4 apostrophe XK_apostrophe -BX_KEY_4+BX_KEY_ALT_R '{' XK_braceleft -BX_KEY_5+BX_KEY_SHIFT_L '5' XK_5 -BX_KEY_5+BX_KEY_ALT_R '[' XK_bracketleft -BX_KEY_5 '(' XK_parenleft -BX_KEY_6+BX_KEY_SHIFT_L '6' XK_6 -BX_KEY_6+BX_KEY_ALT_R '|' XK_bar -BX_KEY_6 '-' XK_minus -BX_KEY_7+BX_KEY_SHIFT_L '7' XK_7 -BX_KEY_7 'è' XK_egrave -BX_KEY_7+BX_KEY_ALT_R '`' XK_grave -BX_KEY_8+BX_KEY_SHIFT_L '8' XK_8 -BX_KEY_8+BX_KEY_ALT_R backslash XK_backslash -BX_KEY_8 '_' XK_underscore -BX_KEY_9+BX_KEY_SHIFT_L '9' XK_9 -BX_KEY_9+BX_KEY_ALT_R '^' XK_asciicircum -BX_KEY_9 'ç' XK_ccedilla -BX_KEY_A+BX_KEY_SHIFT_L 'Q' XK_Q -BX_KEY_A 'q' XK_q -BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B -BX_KEY_B 'b' XK_b -BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C -BX_KEY_C 'c' XK_c -BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D -BX_KEY_D 'd' XK_d -BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E -BX_KEY_E 'e' XK_e -BX_KEY_E+BX_KEY_ALT_R none XK_EuroSign -BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F -BX_KEY_F 'f' XK_f -BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G -BX_KEY_G 'g' XK_g -BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H -BX_KEY_H 'h' XK_h -BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I -BX_KEY_I 'i' XK_i -BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J -BX_KEY_J 'j' XK_j -BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K -BX_KEY_K 'k' XK_k -BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L -BX_KEY_L 'l' XK_l -BX_KEY_M+BX_KEY_SHIFT_L '?' XK_question -BX_KEY_M ',' XK_comma -BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N -BX_KEY_N 'n' XK_n -BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O -BX_KEY_O 'o' XK_o -BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P -BX_KEY_P 'p' XK_p -BX_KEY_Q+BX_KEY_SHIFT_L 'A' XK_A -BX_KEY_Q 'a' XK_a -BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R -BX_KEY_R 'r' XK_r -BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S -BX_KEY_S 's' XK_s -BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T -BX_KEY_T 't' XK_t -BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U -BX_KEY_U 'u' XK_u -BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V -BX_KEY_V 'v' XK_v -BX_KEY_W+BX_KEY_SHIFT_L 'Z' XK_Z -BX_KEY_W 'z' XK_z -BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X -BX_KEY_X 'x' XK_x -BX_KEY_Y+BX_KEY_SHIFT_L 'Y' XK_Y -BX_KEY_Y 'y' XK_y -BX_KEY_Z+BX_KEY_SHIFT_L 'W' XK_W -BX_KEY_Z 'w' XK_w -BX_KEY_F1 none XK_F1 -BX_KEY_F2 none XK_F2 -BX_KEY_F3 none XK_F3 -BX_KEY_F4 none XK_F4 -BX_KEY_F5 none XK_F5 -BX_KEY_F6 none XK_F6 -BX_KEY_F7 none XK_F7 -BX_KEY_F8 none XK_F8 -BX_KEY_F9 none XK_F9 -BX_KEY_F10 none XK_F10 -BX_KEY_F11 none XK_F11 -BX_KEY_F12 none XK_F12 -BX_KEY_ALT_L none XK_Alt_L -BX_KEY_ALT_L none XK_Meta_L -BX_KEY_ALT_R none XK_Alt_R -BX_KEY_ALT_R none XK_Mode_switch -BX_KEY_ALT_R none XK_Multi_key -BX_KEY_BACKSLASH '*' XK_asterisk -BX_KEY_BACKSLASH+BX_KEY_SHIFT_L 'µ' XK_mu -BX_KEY_BACKSPACE none XK_BackSpace -BX_KEY_CAPS_LOCK none XK_Caps_Lock -BX_KEY_COMMA+BX_KEY_SHIFT_L '.' XK_period -BX_KEY_COMMA ';' XK_semicolon -BX_KEY_CTRL_L none XK_Control_L -BX_KEY_CTRL_R none XK_Control_R -BX_KEY_DELETE none XK_Delete -BX_KEY_DOWN none XK_Down -BX_KEY_END none XK_End -BX_KEY_ENTER return XK_Return -BX_KEY_EQUALS+BX_KEY_ALT_R '}' XK_braceright -BX_KEY_EQUALS '=' XK_equal -BX_KEY_EQUALS+BX_KEY_SHIFT_L '+' XK_plus -BX_KEY_ESC none XK_Escape -BX_KEY_GRAVE '²' XK_twosuperior -BX_KEY_HOME none XK_Home -BX_KEY_INSERT none XK_Insert -BX_KEY_KP_5 none XK_KP_5 -BX_KEY_KP_5 none XK_KP_Begin -BX_KEY_KP_ADD none XK_KP_Add -BX_KEY_KP_DELETE none XK_KP_Decimal -BX_KEY_KP_DELETE none XK_KP_Delete -BX_KEY_KP_DIVIDE none XK_KP_Divide -BX_KEY_KP_DOWN none XK_KP_2 -BX_KEY_KP_DOWN none XK_KP_Down -BX_KEY_KP_END none XK_KP_1 -BX_KEY_KP_END none XK_KP_End -BX_KEY_KP_ENTER none XK_KP_Enter -BX_KEY_KP_HOME none XK_KP_7 -BX_KEY_KP_HOME none XK_KP_Home -BX_KEY_KP_INSERT none XK_KP_0 -BX_KEY_KP_INSERT none XK_KP_Insert -BX_KEY_KP_LEFT none XK_KP_4 -BX_KEY_KP_LEFT none XK_KP_Left -BX_KEY_KP_MULTIPLY none XK_KP_Multiply -BX_KEY_KP_PAGE_DOWN none XK_KP_3 -BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down -BX_KEY_KP_PAGE_UP none XK_KP_9 -BX_KEY_KP_PAGE_UP none XK_KP_Page_Up -BX_KEY_KP_RIGHT none XK_KP_6 -BX_KEY_KP_RIGHT none XK_KP_Right -BX_KEY_KP_SUBTRACT none XK_KP_Subtract -BX_KEY_KP_UP none XK_KP_8 -BX_KEY_KP_UP none XK_KP_Up -BX_KEY_LEFT none XK_Left -BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '>' XK_greater -BX_KEY_LEFT_BACKSLASH '<' XK_less -BX_KEY_LEFT_BRACKET '^' XK_dead_circumflex -BX_KEY_LEFT_BRACKET none XK_dead_diaeresis -BX_KEY_MENU none XK_Menu -BX_KEY_MINUS+BX_KEY_ALT_R ']' XK_bracketright -BX_KEY_MINUS+BX_KEY_SHIFT_L '°' XK_degree -BX_KEY_MINUS ')' XK_parenright -BX_KEY_NUM_LOCK none XK_Num_Lock -BX_KEY_PAGE_DOWN none XK_Page_Down -BX_KEY_PAGE_UP none XK_Page_Up -BX_KEY_PAUSE none XK_Break -BX_KEY_PAUSE none XK_Pause -BX_KEY_PERIOD ':' XK_colon -BX_KEY_PERIOD+BX_KEY_SHIFT_L '/' XK_slash -BX_KEY_PRINT none XK_Print -BX_KEY_PRINT none XK_Sys_Req -BX_KEY_RIGHT none XK_Right -BX_KEY_RIGHT_BRACKET+BX_KEY_ALT_R '¤' XK_currency -BX_KEY_RIGHT_BRACKET '$' XK_dollar -BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '£' XK_sterling -BX_KEY_SCRL_LOCK none XK_Scroll_Lock -BX_KEY_SEMICOLON+BX_KEY_SHIFT_L 'M' XK_M -BX_KEY_SEMICOLON 'm' XK_m -BX_KEY_SHIFT_L none XK_Shift_L -BX_KEY_SHIFT_R none XK_Shift_R -BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L '%' XK_percent -BX_KEY_SINGLE_QUOTE 'ù' XK_ugrave -BX_KEY_SLASH '!' XK_exclam -BX_KEY_SLASH+BX_KEY_SHIFT_L '§' XK_section -BX_KEY_SPACE space XK_space -BX_KEY_TAB none XK_ISO_Left_Tab -BX_KEY_TAB tab XK_Tab -BX_KEY_UP none XK_Up -BX_KEY_WIN_L none XK_Super_L -BX_KEY_WIN_R none XK_Super_R diff --git a/tools/ioemu/gui/keymaps/x11-pc-it.map b/tools/ioemu/gui/keymaps/x11-pc-it.map deleted file mode 100644 index fac365e0ba..0000000000 --- a/tools/ioemu/gui/keymaps/x11-pc-it.map +++ /dev/null @@ -1,207 +0,0 @@ -# Bochs Keymap file -# $Id: x11-pc-it.map,v 1.2 2002/09/25 08:00:25 bdenney Exp $ -# Target: PC(x86) keyboard, IT keymap -# Author: Emanuele Goldoni -# -# The keymap file describes the layout of a keyboard, and how it translates -# into Bochs key codes. -# -# Format: -# BX_Keysym ASCII_equivalent Xwin_Keysym -# -# Or, for keys that require modifiers: -# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym -# -# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in -# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it -# could be any key. Presently a maximum of one modifier is supported, but this -# could be changed in keymap.h (structure def has only one slot for modifier), -# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1 -# modifier). -# -# The ASCII_equivalent must be either apostrophe + one character + apostrophe, -# or one of these keywords: space, return, tab, backslash, apostrophe, none. -# This format is designed to look like a char constant in C, but it's a very -# simple parser. There's no concept of backslash being an escape char. The -# backslash and apostrophe entries are provided for aesthetic purposes only: no -# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are -# ugly. -# -# Xwin_Keysym is the X windows equivalent of the key combination. These -# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h. -# If you're running X windows, Bochs will take each of these Xwin_Keysyms, -# pull off the XK_ in front, and use XStringToKeysym() to change them into -# numerical codes. If this lookup fails, you will get a panic and you need -# to edit the keymap file. -# - -BX_KEY_0 '0' XK_0 -BX_KEY_0+BX_KEY_SHIFT_L '=' XK_equal -BX_KEY_1 '1' XK_1 -BX_KEY_1+BX_KEY_SHIFT_L '!' XK_exclam -BX_KEY_2 '2' XK_2 -BX_KEY_2+BX_KEY_SHIFT_L '"' XK_quotedbl -BX_KEY_3 '3' XK_3 -BX_KEY_3+BX_KEY_SHIFT_L '£' XK_sterling -BX_KEY_4 '4' XK_4 -BX_KEY_4+BX_KEY_SHIFT_L '$' XK_dollar -BX_KEY_5 '5' XK_5 -BX_KEY_5+BX_KEY_SHIFT_L '%' XK_percent -BX_KEY_6 '6' XK_6 -BX_KEY_6+BX_KEY_SHIFT_L '&' XK_ampersand -BX_KEY_7 '7' XK_7 -BX_KEY_7+BX_KEY_SHIFT_L '/' XK_slash -BX_KEY_8 '8' XK_8 -BX_KEY_8+BX_KEY_SHIFT_L '(' XK_parenleft -BX_KEY_9 '9' XK_9 -BX_KEY_9+BX_KEY_SHIFT_L ')' XK_parenright -BX_KEY_A+BX_KEY_SHIFT_L 'A' XK_A -BX_KEY_A 'a' XK_a -BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B -BX_KEY_B 'b' XK_b -BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C -BX_KEY_C 'c' XK_c -BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D -BX_KEY_D 'd' XK_d -BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E -BX_KEY_E 'e' XK_e -BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F -BX_KEY_F 'f' XK_f -BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G -BX_KEY_G 'g' XK_g -BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H -BX_KEY_H 'h' XK_h -BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I -BX_KEY_I 'i' XK_i -BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J -BX_KEY_J 'j' XK_j -BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K -BX_KEY_K 'k' XK_k -BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L -BX_KEY_L 'l' XK_l -BX_KEY_M+BX_KEY_SHIFT_L 'M' XK_M -BX_KEY_M 'm' XK_m -BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N -BX_KEY_N 'n' XK_n -BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O -BX_KEY_O 'o' XK_o -BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P -BX_KEY_P 'p' XK_p -BX_KEY_Q+BX_KEY_SHIFT_L 'Q' XK_Q -BX_KEY_Q 'q' XK_q -BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R -BX_KEY_R 'r' XK_r -BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S -BX_KEY_S 's' XK_s -BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T -BX_KEY_T 't' XK_t -BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U -BX_KEY_U 'u' XK_u -BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V -BX_KEY_V 'v' XK_v -BX_KEY_W+BX_KEY_SHIFT_L 'W' XK_W -BX_KEY_W 'w' XK_w -BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X -BX_KEY_X 'x' XK_x -BX_KEY_Y+BX_KEY_SHIFT_L 'Y' XK_Y -BX_KEY_Y 'y' XK_y -BX_KEY_Z+BX_KEY_SHIFT_L 'Z' XK_Z -BX_KEY_Z 'z' XK_z -BX_KEY_F1 none XK_F1 -BX_KEY_F2 none XK_F2 -BX_KEY_F3 none XK_F3 -BX_KEY_F4 none XK_F4 -BX_KEY_F5 none XK_F5 -BX_KEY_F6 none XK_F6 -BX_KEY_F7 none XK_F7 -BX_KEY_F8 none XK_F8 -BX_KEY_F9 none XK_F9 -BX_KEY_F10 none XK_F10 -BX_KEY_F11 none XK_F11 -BX_KEY_F12 none XK_F12 -BX_KEY_ALT_L none XK_Alt_L -BX_KEY_ALT_L none XK_Meta_L -BX_KEY_ALT_R none XK_Alt_R -BX_KEY_ALT_R none XK_Mode_switch -BX_KEY_ALT_R none XK_Multi_key -BX_KEY_BACKSLASH 'ù' XK_ugrave -BX_KEY_BACKSLASH+BX_KEY_SHIFT_L '§' XK_section -BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '>' XK_greater -BX_KEY_LEFT_BACKSLASH '<' XK_less -BX_KEY_BACKSPACE none XK_BackSpace -BX_KEY_CAPS_LOCK none XK_Caps_Lock -BX_KEY_COMMA ',' XK_comma -BX_KEY_COMMA+BX_KEY_SHIFT_L ';' XK_semicolon -BX_KEY_CTRL_L none XK_Control_L -BX_KEY_CTRL_R none XK_Control_R -BX_KEY_DELETE none XK_Delete -BX_KEY_DOWN none XK_Down -BX_KEY_END none XK_End -BX_KEY_ENTER return XK_Return -BX_KEY_EQUALS 'ì' XK_igrave -BX_KEY_EQUALS+BX_KEY_SHIFT_L '^' XK_asciicircum -BX_KEY_ESC none XK_Escape -BX_KEY_GRAVE+BX_KEY_SHIFT_L '|' XK_bar -BX_KEY_GRAVE backslash XK_backslash -BX_KEY_HOME none XK_Home -BX_KEY_INSERT none XK_Insert -BX_KEY_KP_5 none XK_KP_5 -BX_KEY_KP_5 none XK_KP_Begin -BX_KEY_KP_ADD none XK_KP_Add -BX_KEY_KP_DELETE none XK_KP_Decimal -BX_KEY_KP_DELETE none XK_KP_Delete -BX_KEY_KP_DIVIDE none XK_KP_Divide -BX_KEY_KP_DOWN none XK_KP_2 -BX_KEY_KP_DOWN none XK_KP_Down -BX_KEY_KP_END none XK_KP_1 -BX_KEY_KP_END none XK_KP_End -BX_KEY_KP_ENTER none XK_KP_Enter -BX_KEY_KP_HOME none XK_KP_7 -BX_KEY_KP_HOME none XK_KP_Home -BX_KEY_KP_INSERT none XK_KP_0 -BX_KEY_KP_INSERT none XK_KP_Insert -BX_KEY_KP_LEFT none XK_KP_4 -BX_KEY_KP_LEFT none XK_KP_Left -BX_KEY_KP_MULTIPLY none XK_KP_Multiply -BX_KEY_KP_PAGE_DOWN none XK_KP_3 -BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down -BX_KEY_KP_PAGE_UP none XK_KP_9 -BX_KEY_KP_PAGE_UP none XK_KP_Page_Up -BX_KEY_KP_RIGHT none XK_KP_6 -BX_KEY_KP_RIGHT none XK_KP_Right -BX_KEY_KP_SUBTRACT none XK_KP_Subtract -BX_KEY_KP_UP none XK_KP_8 -BX_KEY_KP_UP none XK_KP_Up -BX_KEY_LEFT none XK_Left -BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L 'é' XK_eacute -BX_KEY_LEFT_BRACKET 'è' XK_egrave -BX_KEY_MENU none XK_Menu -BX_KEY_MINUS apostrophe XK_apostrophe -BX_KEY_MINUS+BX_KEY_SHIFT_L '?' XK_question -BX_KEY_NUM_LOCK none XK_Num_Lock -BX_KEY_PAGE_DOWN none XK_Page_Down -BX_KEY_PAGE_UP none XK_Page_Up -BX_KEY_PAUSE none XK_Break -BX_KEY_PAUSE none XK_Pause -BX_KEY_PERIOD+BX_KEY_SHIFT_L ':' XK_colon -BX_KEY_PERIOD '.' XK_period -BX_KEY_PRINT none XK_Print -BX_KEY_PRINT none XK_Sys_Req -BX_KEY_RIGHT none XK_Right -BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '*' XK_asterisk -BX_KEY_RIGHT_BRACKET '+' XK_plus -BX_KEY_SCRL_LOCK none XK_Scroll_Lock -BX_KEY_SEMICOLON+BX_KEY_SHIFT_L 'ç' XK_ccedilla -BX_KEY_SEMICOLON 'ò' XK_ograve -BX_KEY_SHIFT_L none XK_Shift_L -BX_KEY_SHIFT_R none XK_Shift_R -BX_KEY_SINGLE_QUOTE 'à' XK_agrave -BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L '°' XK_degree -BX_KEY_SLASH+BX_KEY_SHIFT_L '_' XK_underscore -BX_KEY_SLASH '-' XK_minus -BX_KEY_SPACE space XK_space -BX_KEY_TAB none XK_ISO_Left_Tab -BX_KEY_TAB tab XK_Tab -BX_KEY_UP none XK_Up -BX_KEY_WIN_L none XK_Super_L -BX_KEY_WIN_R none XK_Super_R diff --git a/tools/ioemu/gui/keymaps/x11-pc-se.map b/tools/ioemu/gui/keymaps/x11-pc-se.map deleted file mode 100644 index c564ca83c6..0000000000 --- a/tools/ioemu/gui/keymaps/x11-pc-se.map +++ /dev/null @@ -1,278 +0,0 @@ -# Bochs Keymap file -# $Id: x11-pc-se.map,v 1.2 2002/09/25 08:00:25 bdenney Exp $ -# Target: PC(x86) keyboard, SE keymap -# Author: Magnus 'Moggen' Öberg -# -# The keymap file describes the layout of a keyboard, and how it translates -# into Bochs key codes. -# -# Format: -# BX_Keysym ASCII_equivalent Xwin_Keysym -# -# Or, for keys that require modifiers: -# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym -# -# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in -# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it -# could be any key. Presently a maximum of one modifier is supported, but this -# could be changed in keymap.h (structure def has only one slot for modifier), -# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1 -# modifier). -# -# The ASCII_equivalent must be either apostrophe + one character + apostrophe, -# or one of these keywords: space, return, tab, backslash, apostrophe, none. -# This format is designed to look like a char constant in C, but it's a very -# simple parser. There's no concept of backslash being an escape char. The -# backslash and apostrophe entries are provided for aesthetic purposes only: no -# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are -# ugly. -# -# Xwin_Keysym is the X windows equivalent of the key combination. These -# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h. -# If you're running X windows, Bochs will take each of these Xwin_Keysyms, -# pull off the XK_ in front, and use XStringToKeysym() to change them into -# numerical codes. If this lookup fails, you will get a panic and you need -# to edit the keymap file. -# - -# Upper key groups -BX_KEY_ESC none XK_Escape - -BX_KEY_F1 none XK_F1 -BX_KEY_F2 none XK_F2 -BX_KEY_F3 none XK_F3 -BX_KEY_F4 none XK_F4 - -BX_KEY_F5 none XK_F5 -BX_KEY_F6 none XK_F6 -BX_KEY_F7 none XK_F7 -BX_KEY_F8 none XK_F8 - -BX_KEY_F9 none XK_F9 -BX_KEY_F10 none XK_F10 -BX_KEY_F11 none XK_F11 -BX_KEY_F12 none XK_F12 - -BX_KEY_PRINT none XK_Print -BX_KEY_PRINT none XK_Sys_Req -BX_KEY_SCRL_LOCK none XK_Scroll_Lock -BX_KEY_PAUSE none XK_Break -BX_KEY_PAUSE none XK_Pause - -# Main key group -# Row 1 -BX_KEY_GRAVE '§' XK_section -BX_KEY_GRAVE+BX_KEY_SHIFT_L '½' XK_onehalf -BX_KEY_GRAVE+BX_KEY_ALT_R '¶' XK_paragraph -BX_KEY_GRAVE+BX_KEY_SHIFT_L+BX_KEY_ALT_R '¾' XK_threequarters -BX_KEY_1 '1' XK_1 -BX_KEY_1+BX_KEY_SHIFT_L '!' XK_exclam -BX_KEY_1+BX_KEY_ALT_R '¡' XK_exclamdown -BX_KEY_1+BX_KEY_SHIFT_L+BX_KEY_ALT_R '¹' XK_onesuperior -BX_KEY_2 '2' XK_2 -BX_KEY_2+BX_KEY_SHIFT_L '"' XK_quotedbl -BX_KEY_2+BX_KEY_ALT_R '@' XK_at -BX_KEY_2+BX_KEY_SHIFT_L+BX_KEY_ALT_R '²' XK_twosuperior -BX_KEY_3 '3' XK_3 -BX_KEY_3+BX_KEY_SHIFT_L '#' XK_numbersign -BX_KEY_3+BX_KEY_ALT_R '£' XK_sterling -BX_KEY_3+BX_KEY_SHIFT_L+BX_KEY_ALT_R '³' XK_threesuperior -BX_KEY_4 '4' XK_4 -BX_KEY_4+BX_KEY_SHIFT_L '¤' XK_currency -BX_KEY_4+BX_KEY_ALT_R '$' XK_dollar -BX_KEY_4+BX_KEY_SHIFT_L+BX_KEY_ALT_R '¼' XK_onequarter -BX_KEY_5 '5' XK_5 -BX_KEY_5+BX_KEY_SHIFT_L '%' XK_percent -BX_KEY_5+BX_KEY_SHIFT_L+BX_KEY_ALT_R '¢' XK_cent -BX_KEY_6 '6' XK_6 -BX_KEY_6+BX_KEY_SHIFT_L '&' XK_ampersand -BX_KEY_6+BX_KEY_ALT_R '¥' XK_yen -BX_KEY_7 '7' XK_7 -BX_KEY_7+BX_KEY_SHIFT_L '/' XK_slash -BX_KEY_7+BX_KEY_ALT_R '{' XK_braceleft -BX_KEY_7+BX_KEY_SHIFT_L+BX_KEY_ALT_R '÷' XK_division -BX_KEY_8 '8' XK_8 -BX_KEY_8+BX_KEY_SHIFT_L '(' XK_parenleft -BX_KEY_8+BX_KEY_ALT_R '[' XK_bracketleft -BX_KEY_9 '9' XK_9 -BX_KEY_9+BX_KEY_SHIFT_L ')' XK_parenright -BX_KEY_9+BX_KEY_ALT_R ']' XK_bracketright -BX_KEY_0 '0' XK_0 -BX_KEY_0+BX_KEY_SHIFT_L '=' XK_equal -BX_KEY_0+BX_KEY_ALT_R '}' XK_braceright -BX_KEY_0+BX_KEY_SHIFT_L+BX_KEY_ALT_R '°' XK_degree -BX_KEY_MINUS '+' XK_plus -BX_KEY_MINUS+BX_KEY_SHIFT_L '?' XK_question -BX_KEY_MINUS+BX_KEY_ALT_L backslash XK_backslash -BX_KEY_MINUS+BX_KEY_SHIFT_L+BX_KEY_ALT_R '¿' XK_questiondown -BX_KEY_EQUALS none XK_dead_acute -BX_KEY_EQUALS+BX_KEY_SHIFT_L none XK_dead_grave -BX_KEY_EQUALS+BX_KEY_ALT_L '±' XK_plusminus -BX_KEY_EQUALS+BX_KEY_ALT_L+BX_KEY_ALT_R '¬' XK_notsign -BX_KEY_BACKSPACE none XK_BackSpace - -# Row 2 -BX_KEY_TAB tab XK_Tab -BX_KEY_TAB none XK_ISO_Left_Tab -BX_KEY_Q 'q' XK_q -BX_KEY_Q+BX_KEY_SHIFT_L 'Q' XK_Q -BX_KEY_W 'w' XK_w -BX_KEY_W+BX_KEY_SHIFT_L 'W' XK_W -BX_KEY_E 'e' XK_e -BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E -BX_KEY_E+BX_KEY_SHIFT_L+BX_KEY_ALT_R none XK_EuroSign -BX_KEY_R 'r' XK_r -BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R -BX_KEY_R+BX_KEY_ALT_R '®' XK_registered -BX_KEY_T 't' XK_t -BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T -BX_KEY_T+BX_KEY_ALT_R 'þ' XK_thorn -BX_KEY_T+BX_KEY_SHIFT_L+BX_KEY_ALT_R 'Þ' XK_THORN -BX_KEY_Y 'y' XK_y -BX_KEY_Y+BX_KEY_SHIFT_L 'Y' XK_Y -BX_KEY_U 'u' XK_u -BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U -BX_KEY_I 'i' XK_i -BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I -BX_KEY_O 'o' XK_o -BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O -BX_KEY_P 'p' XK_p -BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P -BX_KEY_LEFT_BRACKET 'å' XK_aring -BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L 'Å' XK_Aring -BX_KEY_RIGHT_BRACKET none XK_dead_diaeresis -BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L none XK_dead_circumflex -BX_KEY_RIGHT_BRACKET+BX_KEY_ALT_R none XK_dead_tilde -BX_KEY_ENTER return XK_Return - -# Row 3 -BX_KEY_CAPS_LOCK none XK_Caps_Lock -BX_KEY_A 'a' XK_a -BX_KEY_A+BX_KEY_SHIFT_L 'A' XK_A -BX_KEY_A+BX_KEY_ALT_R 'ª' XK_ordfeminine -BX_KEY_A+BX_KEY_SHIFT_L+BX_KEY_ALT_R 'º' XK_masculine -BX_KEY_S 's' XK_s -BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S -BX_KEY_S+BX_KEY_ALT_R 'ß' XK_ssharp -BX_KEY_D 'd' XK_d -BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D -BX_KEY_D+BX_KEY_ALT_R 'ð' XK_eth -BX_KEY_D+BX_KEY_SHIFT_L+BX_KEY_ALT_R 'Ð' XK_ETH -BX_KEY_F 'f' XK_f -BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F -BX_KEY_G 'g' XK_g -BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G -BX_KEY_H 'h' XK_h -BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H -BX_KEY_J 'j' XK_j -BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J -BX_KEY_K 'k' XK_k -BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K -BX_KEY_L 'l' XK_l -BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L -BX_KEY_SEMICOLON 'ö' XK_odiaeresis -BX_KEY_SEMICOLON+BX_KEY_SHIFT_L 'Ö' XK_Odiaeresis -BX_KEY_SEMICOLON+BX_KEY_ALT_R 'ø' XK_oslash -BX_KEY_SEMICOLON+BX_KEY_SHIFT_L+BX_KEY_ALT_R 'Ø' XK_Ooblique -BX_KEY_SINGLE_QUOTE 'ä' XK_adiaeresis -BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L 'Ä' XK_Adiaeresis -BX_KEY_SINGLE_QUOTE+BX_KEY_ALT_R 'æ' XK_ae -BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L+BX_KEY_ALT_R 'Æ' XK_AE -BX_KEY_BACKSLASH apostrophe XK_apostrophe -BX_KEY_BACKSLASH+BX_KEY_SHIFT_L '*' XK_asterisk -BX_KEY_BACKSLASH+BX_KEY_ALT_R '´' XK_acute -BX_KEY_BACKSLASH+BX_KEY_SHIFT_L+BX_KEY_ALT_R '×' XK_multiply - -# Row 4 -BX_KEY_SHIFT_L none XK_Shift_L -BX_KEY_LEFT_BACKSLASH '<' XK_less -BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '>' XK_greater -BX_KEY_LEFT_BACKSLASH+BX_KEY_ALT_R '|' XK_bar -BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L+BX_KEY_ALT_R '¦' XK_brokenbar -BX_KEY_Z 'z' XK_z -BX_KEY_Z+BX_KEY_SHIFT_L 'Z' XK_Z -BX_KEY_Z+BX_KEY_ALT_R '«' XK_guillemotleft -BX_KEY_X 'x' XK_x -BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X -BX_KEY_X+BX_KEY_ALT_R '»' XK_guillemotright -BX_KEY_C 'c' XK_c -BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C -BX_KEY_C+BX_KEY_ALT_R '©' XK_copyright -BX_KEY_V 'v' XK_v -BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V -BX_KEY_V+BX_KEY_SHIFT_L+BX_KEY_ALT_R '`' XK_grave -BX_KEY_B 'b' XK_b -BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B -BX_KEY_N 'n' XK_n -BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N -BX_KEY_M 'm' XK_m -BX_KEY_M+BX_KEY_SHIFT_L 'M' XK_M -BX_KEY_M+BX_KEY_ALT_R 'µ' XK_mu -BX_KEY_COMMA ',' XK_comma -BX_KEY_COMMA+BX_KEY_SHIFT_L ';' XK_semicolon -BX_KEY_PERIOD '.' XK_period -BX_KEY_PERIOD+BX_KEY_SHIFT_L ':' XK_colon -BX_KEY_PERIOD+BX_KEY_ALT_R '·' XK_periodcentered -BX_KEY_SLASH '-' XK_minus -BX_KEY_SLASH+BX_KEY_SHIFT '_' XK_underscore -BX_KEY_SLASH+BX_KEY_ALT_R '­' XK_hyphen -BX_KEY_SLASH+BX_KEY_SHIFT+BX_KEY_ALT_R '­' XK_macron -BX_KEY_SHIFT_R none XK_Shift_R - -# Row 5 -BX_KEY_CTRL_L none XK_Control_L -BX_KEY_WIN_L none XK_Super_L -BX_KEY_ALT_L none XK_Alt_L -BX_KEY_ALT_L none XK_Meta_L -BX_KEY_SPACE space XK_space -BX_KEY_SPACE+BX_KEY_ALT_R none XK_nobreakspace -BX_KEY_ALT_R none XK_Alt_R -BX_KEY_ALT_R none XK_Mode_switch -BX_KEY_ALT_R none XK_Multi_key -BX_KEY_WIN_R none XK_Super_R -BX_KEY_MENU none XK_Menu -BX_KEY_CTRL_R none XK_Control_R - -# Ins/Del/Home/End/PgUp/PgDn -BX_KEY_INSERT none XK_Insert -BX_KEY_DELETE none XK_Delete -BX_KEY_HOME none XK_Home -BX_KEY_END none XK_End -BX_KEY_PAGE_UP none XK_Page_Up -BX_KEY_PAGE_DOWN none XK_Page_Down - -# Arrow keys -BX_KEY_LEFT none XK_Left -BX_KEY_RIGHT none XK_Right -BX_KEY_UP none XK_Up -BX_KEY_DOWN none XK_Down - -# Numerical keypad -BX_KEY_NUM_LOCK none XK_Num_Lock -BX_KEY_KP_DIVIDE none XK_KP_Divide -BX_KEY_KP_MULTIPLY none XK_KP_Multiply -BX_KEY_KP_SUBTRACT none XK_KP_Subtract -BX_KEY_KP_ADD none XK_KP_Add -BX_KEY_KP_ENTER none XK_KP_Enter -BX_KEY_KP_HOME none XK_KP_7 -BX_KEY_KP_HOME none XK_KP_Home -BX_KEY_KP_UP none XK_KP_8 -BX_KEY_KP_UP none XK_KP_Up -BX_KEY_KP_PAGE_UP none XK_KP_9 -BX_KEY_KP_PAGE_UP none XK_KP_Page_Up -BX_KEY_KP_LEFT none XK_KP_4 -BX_KEY_KP_LEFT none XK_KP_Left -BX_KEY_KP_5 none XK_KP_5 -BX_KEY_KP_5 none XK_KP_Begin -BX_KEY_KP_RIGHT none XK_KP_6 -BX_KEY_KP_RIGHT none XK_KP_Right -BX_KEY_KP_END none XK_KP_1 -BX_KEY_KP_END none XK_KP_End -BX_KEY_KP_DOWN none XK_KP_2 -BX_KEY_KP_DOWN none XK_KP_Down -BX_KEY_KP_PAGE_DOWN none XK_KP_3 -BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down -BX_KEY_KP_INSERT none XK_KP_0 -BX_KEY_KP_INSERT none XK_KP_Insert -BX_KEY_KP_DELETE none XK_KP_Decimal -BX_KEY_KP_DELETE none XK_KP_Delete diff --git a/tools/ioemu/gui/keymaps/x11-pc-uk.map b/tools/ioemu/gui/keymaps/x11-pc-uk.map deleted file mode 100644 index 05abbe4f83..0000000000 --- a/tools/ioemu/gui/keymaps/x11-pc-uk.map +++ /dev/null @@ -1,209 +0,0 @@ -# Bochs Keymap file -# $Id: x11-pc-uk.map,v 1.1 2002/12/11 21:35:50 bdenney Exp $ -# Target: PC(x86) keyboard, UK keymap -# Author: Denis Lenihan -# -# The keymap file describes the layout of a keyboard, and how it translates -# into Bochs key codes. -# -# Format: -# BX_Keysym ASCII_equivalent Xwin_Keysym -# -# Or, for keys that require modifiers: -# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym -# -# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in -# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it -# could be any key. Presently a maximum of one modifier is supported, but this -# could be changed in keymap.h (structure def has only one slot for modifier), -# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1 -# modifier). -# -# The ASCII_equivalent must be either apostrophe + one character + apostrophe, -# or one of these keywords: space, return, tab, backslash, apostrophe, none. -# This format is designed to look like a char constant in C, but it's a very -# simple parser. There's no concept of backslash being an escape char. The -# backslash and apostrophe entries are provided for aesthetic purposes only: no -# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are -# ugly. -# -# Xwin_Keysym is the X windows equivalent of the key combination. These -# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h. -# If you're running X windows, Bochs will take each of these Xwin_Keysyms, -# pull off the XK_ in front, and use XStringToKeysym() to change them into -# numerical codes. If this lookup fails, you will get a panic and you need -# to edit the keymap file. -# - -BX_KEY_0 '0' XK_0 -BX_KEY_0+BX_KEY_SHIFT_L ')' XK_parenright -BX_KEY_1 '1' XK_1 -BX_KEY_1+BX_KEY_SHIFT_L '!' XK_exclam -BX_KEY_2 '2' XK_2 -BX_KEY_2+BX_KEY_SHIFT_L '"' XK_quotedbl -BX_KEY_3 '3' XK_3 -BX_KEY_3+BX_KEY_SHIFT_L '£' XK_sterling -BX_KEY_3+BX_KEY_ALT_R '|' XK_EuroSign -BX_KEY_4 '4' XK_4 -BX_KEY_4+BX_KEY_SHIFT_L '$' XK_dollar -BX_KEY_5 '5' XK_5 -BX_KEY_5+BX_KEY_SHIFT_L '%' XK_percent -BX_KEY_6 '6' XK_6 -BX_KEY_6+BX_KEY_SHIFT_L '^' XK_asciicircum -BX_KEY_7 '7' XK_7 -BX_KEY_7+BX_KEY_SHIFT_L '&' XK_ampersand -BX_KEY_8 '8' XK_8 -BX_KEY_8+BX_KEY_SHIFT_L '*' XK_asterisk -BX_KEY_9 '9' XK_9 -BX_KEY_9+BX_KEY_SHIFT_L '(' XK_parenleft -BX_KEY_A+BX_KEY_SHIFT_L 'A' XK_A -BX_KEY_A 'a' XK_a -BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B -BX_KEY_B 'b' XK_b -BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C -BX_KEY_C 'c' XK_c -BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D -BX_KEY_D 'd' XK_d -BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E -BX_KEY_E 'e' XK_e -BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F -BX_KEY_F 'f' XK_f -BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G -BX_KEY_G 'g' XK_g -BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H -BX_KEY_H 'h' XK_h -BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I -BX_KEY_I 'i' XK_i -BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J -BX_KEY_J 'j' XK_j -BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K -BX_KEY_K 'k' XK_k -BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L -BX_KEY_L 'l' XK_l -BX_KEY_M+BX_KEY_SHIFT_L 'M' XK_M -BX_KEY_M 'm' XK_m -BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N -BX_KEY_N 'n' XK_n -BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O -BX_KEY_O 'o' XK_o -BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P -BX_KEY_P 'p' XK_p -BX_KEY_Q+BX_KEY_SHIFT_L 'Q' XK_Q -BX_KEY_Q 'q' XK_q -BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R -BX_KEY_R 'r' XK_r -BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S -BX_KEY_S 's' XK_s -BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T -BX_KEY_T 't' XK_t -BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U -BX_KEY_U 'u' XK_u -BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V -BX_KEY_V 'v' XK_v -BX_KEY_W+BX_KEY_SHIFT_L 'W' XK_W -BX_KEY_W 'w' XK_w -BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X -BX_KEY_X 'x' XK_x -BX_KEY_Y+BX_KEY_SHIFT_L 'Y' XK_Y -BX_KEY_Y 'y' XK_y -BX_KEY_Z+BX_KEY_SHIFT_L 'Z' XK_Z -BX_KEY_Z 'z' XK_z -BX_KEY_F1 none XK_F1 -BX_KEY_F2 none XK_F2 -BX_KEY_F3 none XK_F3 -BX_KEY_F4 none XK_F4 -BX_KEY_F5 none XK_F5 -BX_KEY_F6 none XK_F6 -BX_KEY_F7 none XK_F7 -BX_KEY_F8 none XK_F8 -BX_KEY_F9 none XK_F9 -BX_KEY_F10 none XK_F10 -BX_KEY_F11 none XK_F11 -BX_KEY_F12 none XK_F12 -BX_KEY_ALT_L none XK_Alt_L -BX_KEY_ALT_L none XK_Meta_L -BX_KEY_ALT_R none XK_Alt_R -BX_KEY_ALT_R none XK_Mode_switch -BX_KEY_ALT_R none XK_Multi_key -BX_KEY_LEFT_BACKSLASH '\' XK_backslash -BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '|' XK_bar -BX_KEY_BACKSLASH '~' XK_asciitilde -BX_KEY_BACKSLASH+BX_KEY_SHIFT_L '#' XK_numbersign -BX_KEY_BACKSPACE none XK_BackSpace -BX_KEY_CAPS_LOCK none XK_Caps_Lock -BX_KEY_COMMA ',' XK_comma -BX_KEY_COMMA+BX_KEY_SHIFT_L '<' XK_less -BX_KEY_CTRL_L none XK_Control_L -BX_KEY_CTRL_R none XK_Control_R -BX_KEY_DELETE none XK_Delete -BX_KEY_DOWN none XK_Down -BX_KEY_END none XK_End -BX_KEY_ENTER return XK_Return -BX_KEY_EQUALS '=' XK_equal -BX_KEY_EQUALS+BX_KEY_SHIFT_L '+' XK_plus -BX_KEY_ESC none XK_Escape -BX_KEY_GRAVE+BX_KEY_SHIFT_L '¬' XK_notsign -BX_KEY_GRAVE '`' XK_grave -BX_KEY_GRAVE+BX_KEY_ALT_R '|' XK_bar -BX_KEY_HOME none XK_Home -BX_KEY_INSERT none XK_Insert -BX_KEY_KP_5 none XK_KP_5 -BX_KEY_KP_5 none XK_KP_Begin -BX_KEY_KP_ADD none XK_KP_Add -BX_KEY_KP_DELETE none XK_KP_Decimal -BX_KEY_KP_DELETE none XK_KP_Delete -BX_KEY_KP_DIVIDE none XK_KP_Divide -BX_KEY_KP_DOWN none XK_KP_2 -BX_KEY_KP_DOWN none XK_KP_Down -BX_KEY_KP_END none XK_KP_1 -BX_KEY_KP_END none XK_KP_End -BX_KEY_KP_ENTER none XK_KP_Enter -BX_KEY_KP_HOME none XK_KP_7 -BX_KEY_KP_HOME none XK_KP_Home -BX_KEY_KP_INSERT none XK_KP_0 -BX_KEY_KP_INSERT none XK_KP_Insert -BX_KEY_KP_LEFT none XK_KP_4 -BX_KEY_KP_LEFT none XK_KP_Left -BX_KEY_KP_MULTIPLY none XK_KP_Multiply -BX_KEY_KP_PAGE_DOWN none XK_KP_3 -BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down -BX_KEY_KP_PAGE_UP none XK_KP_9 -BX_KEY_KP_PAGE_UP none XK_KP_Page_Up -BX_KEY_KP_RIGHT none XK_KP_6 -BX_KEY_KP_RIGHT none XK_KP_Right -BX_KEY_KP_SUBTRACT none XK_KP_Subtract -BX_KEY_KP_UP none XK_KP_8 -BX_KEY_KP_UP none XK_KP_Up -BX_KEY_LEFT none XK_Left -BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L '{' XK_braceleft -BX_KEY_LEFT_BRACKET '[' XK_bracketleft -BX_KEY_MENU none XK_Menu -BX_KEY_MINUS '-' XK_minus -BX_KEY_MINUS+BX_KEY_SHIFT_L '_' XK_underscore -BX_KEY_NUM_LOCK none XK_Num_Lock -BX_KEY_PAGE_DOWN none XK_Page_Down -BX_KEY_PAGE_UP none XK_Page_Up -BX_KEY_PAUSE none XK_Break -BX_KEY_PAUSE none XK_Pause -BX_KEY_PERIOD+BX_KEY_SHIFT_L '>' XK_greater -BX_KEY_PERIOD '.' XK_period -BX_KEY_PRINT none XK_Print -BX_KEY_PRINT none XK_Sys_Req -BX_KEY_RIGHT none XK_Right -BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '}' XK_braceright -BX_KEY_RIGHT_BRACKET ']' XK_bracketright -BX_KEY_SCRL_LOCK none XK_Scroll_Lock -BX_KEY_SEMICOLON+BX_KEY_SHIFT_L ':' XK_colon -BX_KEY_SEMICOLON ';' XK_semicolon -BX_KEY_SHIFT_L none XK_Shift_L -BX_KEY_SHIFT_R none XK_Shift_R -BX_KEY_SINGLE_QUOTE apostrophe XK_apostrophe -BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L '@' XK_at -BX_KEY_SLASH+BX_KEY_SHIFT_L '?' XK_question -BX_KEY_SLASH '/' XK_slash -BX_KEY_SPACE space XK_space -BX_KEY_TAB none XK_ISO_Left_Tab -BX_KEY_TAB tab XK_Tab -BX_KEY_UP none XK_Up -BX_KEY_WIN_L none XK_Super_L -BX_KEY_WIN_R none XK_Super_R diff --git a/tools/ioemu/gui/keymaps/x11-pc-us.map b/tools/ioemu/gui/keymaps/x11-pc-us.map deleted file mode 100644 index 8cda7a8a13..0000000000 --- a/tools/ioemu/gui/keymaps/x11-pc-us.map +++ /dev/null @@ -1,205 +0,0 @@ -# Bochs Keymap file -# $Id: x11-pc-us.map,v 1.3 2002/09/25 08:00:25 bdenney Exp $ -# Target: PC(x86) keyboard, US keymap -# Author: Christophe Bothamy, Bryce Denney -# -# The keymap file describes the layout of a keyboard, and how it translates -# into Bochs key codes. -# -# Format: -# BX_Keysym ASCII_equivalent Xwin_Keysym -# -# Or, for keys that require modifiers: -# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym -# -# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in -# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it -# could be any key. Presently a maximum of one modifier is supported, but this -# could be changed in keymap.h (structure def has only one slot for modifier), -# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1 -# modifier). -# -# The ASCII_equivalent must be either apostrophe + one character + apostrophe, -# or one of these keywords: space, return, tab, backslash, apostrophe, none. -# This format is designed to look like a char constant in C, but it's a very -# simple parser. There's no concept of backslash being an escape char. The -# backslash and apostrophe entries are provided for aesthetic purposes only: no -# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are -# ugly. -# -# Xwin_Keysym is the X windows equivalent of the key combination. These -# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h. -# If you're running X windows, Bochs will take each of these Xwin_Keysyms, -# pull off the XK_ in front, and use XStringToKeysym() to change them into -# numerical codes. If this lookup fails, you will get a panic and you need -# to edit the keymap file. -# - -BX_KEY_0 '0' XK_0 -BX_KEY_0+BX_KEY_SHIFT_L ')' XK_parenright -BX_KEY_1 '1' XK_1 -BX_KEY_1+BX_KEY_SHIFT_L '!' XK_exclam -BX_KEY_2 '2' XK_2 -BX_KEY_2+BX_KEY_SHIFT_L '@' XK_at -BX_KEY_3 '3' XK_3 -BX_KEY_3+BX_KEY_SHIFT_L '#' XK_numbersign -BX_KEY_4 '4' XK_4 -BX_KEY_4+BX_KEY_SHIFT_L '$' XK_dollar -BX_KEY_5 '5' XK_5 -BX_KEY_5+BX_KEY_SHIFT_L '%' XK_percent -BX_KEY_6 '6' XK_6 -BX_KEY_6+BX_KEY_SHIFT_L '^' XK_asciicircum -BX_KEY_7 '7' XK_7 -BX_KEY_7+BX_KEY_SHIFT_L '&' XK_ampersand -BX_KEY_8 '8' XK_8 -BX_KEY_8+BX_KEY_SHIFT_L '*' XK_asterisk -BX_KEY_9 '9' XK_9 -BX_KEY_9+BX_KEY_SHIFT_L '(' XK_parenleft -BX_KEY_A+BX_KEY_SHIFT_L 'A' XK_A -BX_KEY_A 'a' XK_a -BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B -BX_KEY_B 'b' XK_b -BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C -BX_KEY_C 'c' XK_c -BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D -BX_KEY_D 'd' XK_d -BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E -BX_KEY_E 'e' XK_e -BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F -BX_KEY_F 'f' XK_f -BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G -BX_KEY_G 'g' XK_g -BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H -BX_KEY_H 'h' XK_h -BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I -BX_KEY_I 'i' XK_i -BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J -BX_KEY_J 'j' XK_j -BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K -BX_KEY_K 'k' XK_k -BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L -BX_KEY_L 'l' XK_l -BX_KEY_M+BX_KEY_SHIFT_L 'M' XK_M -BX_KEY_M 'm' XK_m -BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N -BX_KEY_N 'n' XK_n -BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O -BX_KEY_O 'o' XK_o -BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P -BX_KEY_P 'p' XK_p -BX_KEY_Q+BX_KEY_SHIFT_L 'Q' XK_Q -BX_KEY_Q 'q' XK_q -BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R -BX_KEY_R 'r' XK_r -BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S -BX_KEY_S 's' XK_s -BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T -BX_KEY_T 't' XK_t -BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U -BX_KEY_U 'u' XK_u -BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V -BX_KEY_V 'v' XK_v -BX_KEY_W+BX_KEY_SHIFT_L 'W' XK_W -BX_KEY_W 'w' XK_w -BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X -BX_KEY_X 'x' XK_x -BX_KEY_Y+BX_KEY_SHIFT_L 'Y' XK_Y -BX_KEY_Y 'y' XK_y -BX_KEY_Z+BX_KEY_SHIFT_L 'Z' XK_Z -BX_KEY_Z 'z' XK_z -BX_KEY_F1 none XK_F1 -BX_KEY_F2 none XK_F2 -BX_KEY_F3 none XK_F3 -BX_KEY_F4 none XK_F4 -BX_KEY_F5 none XK_F5 -BX_KEY_F6 none XK_F6 -BX_KEY_F7 none XK_F7 -BX_KEY_F8 none XK_F8 -BX_KEY_F9 none XK_F9 -BX_KEY_F10 none XK_F10 -BX_KEY_F11 none XK_F11 -BX_KEY_F12 none XK_F12 -BX_KEY_ALT_L none XK_Alt_L -BX_KEY_ALT_L none XK_Meta_L -BX_KEY_ALT_R none XK_Alt_R -BX_KEY_ALT_R none XK_Mode_switch -BX_KEY_ALT_R none XK_Multi_key -BX_KEY_BACKSLASH backslash XK_backslash -BX_KEY_BACKSLASH+BX_KEY_SHIFT_L '|' XK_bar -BX_KEY_BACKSPACE none XK_BackSpace -BX_KEY_CAPS_LOCK none XK_Caps_Lock -BX_KEY_COMMA ',' XK_comma -BX_KEY_COMMA+BX_KEY_SHIFT_L '<' XK_less -BX_KEY_CTRL_L none XK_Control_L -BX_KEY_CTRL_R none XK_Control_R -BX_KEY_DELETE none XK_Delete -BX_KEY_DOWN none XK_Down -BX_KEY_END none XK_End -BX_KEY_ENTER return XK_Return -BX_KEY_EQUALS '=' XK_equal -BX_KEY_EQUALS+BX_KEY_SHIFT_L '+' XK_plus -BX_KEY_ESC none XK_Escape -BX_KEY_GRAVE+BX_KEY_SHIFT_L '~' XK_asciitilde -BX_KEY_GRAVE '`' XK_grave -BX_KEY_HOME none XK_Home -BX_KEY_INSERT none XK_Insert -BX_KEY_KP_5 none XK_KP_5 -BX_KEY_KP_5 none XK_KP_Begin -BX_KEY_KP_ADD none XK_KP_Add -BX_KEY_KP_DELETE none XK_KP_Decimal -BX_KEY_KP_DELETE none XK_KP_Delete -BX_KEY_KP_DIVIDE none XK_KP_Divide -BX_KEY_KP_DOWN none XK_KP_2 -BX_KEY_KP_DOWN none XK_KP_Down -BX_KEY_KP_END none XK_KP_1 -BX_KEY_KP_END none XK_KP_End -BX_KEY_KP_ENTER none XK_KP_Enter -BX_KEY_KP_HOME none XK_KP_7 -BX_KEY_KP_HOME none XK_KP_Home -BX_KEY_KP_INSERT none XK_KP_0 -BX_KEY_KP_INSERT none XK_KP_Insert -BX_KEY_KP_LEFT none XK_KP_4 -BX_KEY_KP_LEFT none XK_KP_Left -BX_KEY_KP_MULTIPLY none XK_KP_Multiply -BX_KEY_KP_PAGE_DOWN none XK_KP_3 -BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down -BX_KEY_KP_PAGE_UP none XK_KP_9 -BX_KEY_KP_PAGE_UP none XK_KP_Page_Up -BX_KEY_KP_RIGHT none XK_KP_6 -BX_KEY_KP_RIGHT none XK_KP_Right -BX_KEY_KP_SUBTRACT none XK_KP_Subtract -BX_KEY_KP_UP none XK_KP_8 -BX_KEY_KP_UP none XK_KP_Up -BX_KEY_LEFT none XK_Left -BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L '{' XK_braceleft -BX_KEY_LEFT_BRACKET '[' XK_bracketleft -BX_KEY_MENU none XK_Menu -BX_KEY_MINUS '-' XK_minus -BX_KEY_MINUS+BX_KEY_SHIFT_L '_' XK_underscore -BX_KEY_NUM_LOCK none XK_Num_Lock -BX_KEY_PAGE_DOWN none XK_Page_Down -BX_KEY_PAGE_UP none XK_Page_Up -BX_KEY_PAUSE none XK_Break -BX_KEY_PAUSE none XK_Pause -BX_KEY_PERIOD+BX_KEY_SHIFT_L '>' XK_greater -BX_KEY_PERIOD '.' XK_period -BX_KEY_PRINT none XK_Print -BX_KEY_PRINT none XK_Sys_Req -BX_KEY_RIGHT none XK_Right -BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '}' XK_braceright -BX_KEY_RIGHT_BRACKET ']' XK_bracketright -BX_KEY_SCRL_LOCK none XK_Scroll_Lock -BX_KEY_SEMICOLON+BX_KEY_SHIFT_L ':' XK_colon -BX_KEY_SEMICOLON ';' XK_semicolon -BX_KEY_SHIFT_L none XK_Shift_L -BX_KEY_SHIFT_R none XK_Shift_R -BX_KEY_SINGLE_QUOTE apostrophe XK_apostrophe -BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L '"' XK_quotedbl -BX_KEY_SLASH+BX_KEY_SHIFT_L '?' XK_question -BX_KEY_SLASH '/' XK_slash -BX_KEY_SPACE space XK_space -BX_KEY_TAB none XK_ISO_Left_Tab -BX_KEY_TAB tab XK_Tab -BX_KEY_UP none XK_Up -BX_KEY_WIN_L none XK_Super_L -BX_KEY_WIN_R none XK_Super_R diff --git a/tools/ioemu/gui/nogui.cc b/tools/ioemu/gui/nogui.cc deleted file mode 100644 index dd56d9d854..0000000000 --- a/tools/ioemu/gui/nogui.cc +++ /dev/null @@ -1,336 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: nogui.cc,v 1.21 2003/06/28 08:04:31 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#include "icon_bochs.h" - -class bx_nogui_gui_c : public bx_gui_c { -public: - bx_nogui_gui_c (void) {} - DECLARE_GUI_VIRTUAL_METHODS() -}; - -// declare one instance of the gui object and call macro to insert the -// plugin code -static bx_nogui_gui_c *theGui = NULL; -IMPLEMENT_GUI_PLUGIN_CODE(nogui) - -#define LOG_THIS theGui-> - -// This file defines stubs for the GUI interface, which is a -// place to start if you want to port bochs to a platform, for -// which there is no support for your native GUI, or if you want to compile -// bochs without any native GUI support (no output window or -// keyboard input will be possible). -// Look in 'x.cc', 'beos.cc', and 'win32.cc' for specific -// implementations of this interface. -Kevin - - - -// ::SPECIFIC_INIT() -// -// Called from gui.cc, once upon program startup, to allow for the -// specific GUI code (X11, BeOS, ...) to be initialized. -// -// argc, argv: not used right now, but the intention is to pass native GUI -// specific options from the command line. (X11 options, BeOS options,...) -// -// tilewidth, tileheight: for optimization, graphics_tile_update() passes -// only updated regions of the screen to the gui code to be redrawn. -// These define the dimensions of a region (tile). -// headerbar_y: A headerbar (toolbar) is display on the top of the -// VGA window, showing floppy status, and other information. It -// always assumes the width of the current VGA mode width, but -// it's height is defined by this parameter. - - void -bx_nogui_gui_c::specific_init(int argc, char **argv, unsigned tilewidth, unsigned tileheight, - unsigned headerbar_y) -{ - put("NGUI"); - UNUSED(argc); - UNUSED(argv); - UNUSED(tilewidth); - UNUSED(tileheight); - UNUSED(headerbar_y); - - UNUSED(bochs_icon_bits); // global variable - - if (bx_options.Oprivate_colormap->get ()) { - BX_INFO(("private_colormap option ignored.")); - } -} - - -// ::HANDLE_EVENTS() -// -// Called periodically (vga_update_interval in .bochsrc) so the -// the gui code can poll for keyboard, mouse, and other -// relevant events. - - void -bx_nogui_gui_c::handle_events(void) -{ -} - - -// ::FLUSH() -// -// Called periodically, requesting that the gui code flush all pending -// screen update requests. - - void -bx_nogui_gui_c::flush(void) -{ -} - - -// ::CLEAR_SCREEN() -// -// Called to request that the VGA region is cleared. Don't -// clear the area that defines the headerbar. - - void -bx_nogui_gui_c::clear_screen(void) -{ -} - - - -// ::TEXT_UPDATE() -// -// Called in a VGA text mode, to update the screen with -// new content. -// -// old_text: array of character/attributes making up the contents -// of the screen from the last call. See below -// new_text: array of character/attributes making up the current -// contents, which should now be displayed. See below -// -// format of old_text & new_text: each is 4000 bytes long. -// This represents 80 characters wide by 25 high, with -// each character being 2 bytes. The first by is the -// character value, the second is the attribute byte. -// I currently don't handle the attribute byte. -// -// cursor_x: new x location of cursor -// cursor_y: new y location of cursor - - void -bx_nogui_gui_c::text_update(Bit8u *old_text, Bit8u *new_text, - unsigned long cursor_x, unsigned long cursor_y, - bx_vga_tminfo_t tm_info, unsigned nrows) -{ - UNUSED(old_text); - UNUSED(new_text); - UNUSED(cursor_x); - UNUSED(cursor_y); - UNUSED(tm_info); - UNUSED(nrows); -} - - int -bx_nogui_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes) -{ - UNUSED(bytes); - UNUSED(nbytes); - return 0; -} - - int -bx_nogui_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len) -{ - UNUSED(text_snapshot); - UNUSED(len); - return 0; -} - - -// ::PALETTE_CHANGE() -// -// Allocate a color in the native GUI, for this color, and put -// it in the colormap location 'index'. -// returns: 0=no screen update needed (color map change has direct effect) -// 1=screen updated needed (redraw using current colormap) - - bx_bool -bx_nogui_gui_c::palette_change(unsigned index, unsigned red, unsigned green, unsigned blue) -{ - UNUSED(index); - UNUSED(red); - UNUSED(green); - UNUSED(blue); - return(0); -} - - -// ::GRAPHICS_TILE_UPDATE() -// -// Called to request that a tile of graphics be drawn to the -// screen, since info in this region has changed. -// -// tile: array of 8bit values representing a block of pixels with -// dimension equal to the 'tilewidth' & 'tileheight' parameters to -// ::specific_init(). Each value specifies an index into the -// array of colors you allocated for ::palette_change() -// x0: x origin of tile -// y0: y origin of tile -// -// note: origin of tile and of window based on (0,0) being in the upper -// left of the window. - - void -bx_nogui_gui_c::graphics_tile_update(Bit8u *tile, unsigned x0, unsigned y0) -{ - UNUSED(tile); - UNUSED(x0); - UNUSED(y0); -} - - - -// ::DIMENSION_UPDATE() -// -// Called when the VGA mode changes it's X,Y dimensions. -// Resize the window to this size, but you need to add on -// the height of the headerbar to the Y value. -// -// x: new VGA x size -// y: new VGA y size (add headerbar_y parameter from ::specific_init(). -// fheight: new VGA character height in text mode -// fwidth : new VGA character width in text mode -// bpp : bits per pixel in graphics mode - - void -bx_nogui_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, unsigned fwidth, unsigned bpp) -{ - UNUSED(x); - UNUSED(y); - UNUSED(fheight); - UNUSED(fwidth); - UNUSED(bpp); -} - - -// ::CREATE_BITMAP() -// -// Create a monochrome bitmap of size 'xdim' by 'ydim', which will -// be drawn in the headerbar. Return an integer ID to the bitmap, -// with which the bitmap can be referenced later. -// -// bmap: packed 8 pixels-per-byte bitmap. The pixel order is: -// bit0 is the left most pixel, bit7 is the right most pixel. -// xdim: x dimension of bitmap -// ydim: y dimension of bitmap - - unsigned -bx_nogui_gui_c::create_bitmap(const unsigned char *bmap, unsigned xdim, unsigned ydim) -{ - UNUSED(bmap); - UNUSED(xdim); - UNUSED(ydim); - return(0); -} - - -// ::HEADERBAR_BITMAP() -// -// Called to install a bitmap in the bochs headerbar (toolbar). -// -// bmap_id: will correspond to an ID returned from -// ::create_bitmap(). 'alignment' is either BX_GRAVITY_LEFT -// or BX_GRAVITY_RIGHT, meaning install the bitmap in the next -// available leftmost or rightmost space. -// alignment: is either BX_GRAVITY_LEFT or BX_GRAVITY_RIGHT, -// meaning install the bitmap in the next -// available leftmost or rightmost space. -// f: a 'C' function pointer to callback when the mouse is clicked in -// the boundaries of this bitmap. - - unsigned -bx_nogui_gui_c::headerbar_bitmap(unsigned bmap_id, unsigned alignment, void (*f)(void)) -{ - UNUSED(bmap_id); - UNUSED(alignment); - UNUSED(f); - return(0); -} - - -// ::SHOW_HEADERBAR() -// -// Show (redraw) the current headerbar, which is composed of -// currently installed bitmaps. - - void -bx_nogui_gui_c::show_headerbar(void) -{ -} - - -// ::REPLACE_BITMAP() -// -// Replace the bitmap installed in the headerbar ID slot 'hbar_id', -// with the one specified by 'bmap_id'. 'bmap_id' will have -// been generated by ::create_bitmap(). The old and new bitmap -// must be of the same size. This allows the bitmap the user -// sees to change, when some action occurs. For example when -// the user presses on the floppy icon, it then displays -// the ejected status. -// -// hbar_id: headerbar slot ID -// bmap_id: bitmap ID - - void -bx_nogui_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id) -{ - UNUSED(hbar_id); - UNUSED(bmap_id); -} - - -// ::EXIT() -// -// Called before bochs terminates, to allow for a graceful -// exit from the native GUI mechanism. - - void -bx_nogui_gui_c::exit(void) -{ - BX_INFO(("bx_nogui_gui_c::exit() not implemented yet.")); -} - - void -bx_nogui_gui_c::mouse_enabled_changed_specific (bx_bool val) -{ -} diff --git a/tools/ioemu/gui/rfb.cc b/tools/ioemu/gui/rfb.cc deleted file mode 100644 index f67f80e895..0000000000 --- a/tools/ioemu/gui/rfb.cc +++ /dev/null @@ -1,1508 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: rfb.cc,v 1.26.2.1 2004/02/02 22:35:30 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2000 Psyon.Org! -// -// Donald Becker -// http://www.psyon.org -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_WITH_RFB - -#include "icon_bochs.h" -#include "font/vga.bitmap.h" - -class bx_rfb_gui_c : public bx_gui_c { -public: - bx_rfb_gui_c (void) {} - DECLARE_GUI_VIRTUAL_METHODS() -}; - -// declare one instance of the gui object and call macro to insert the -// plugin code -static bx_rfb_gui_c *theGui = NULL; -IMPLEMENT_GUI_PLUGIN_CODE(rfb) - -#define LOG_THIS theGui-> - -#ifdef WIN32 - -#include -#include -#include "rfb.h" - -#else - -#include -#include -#include -#include -#include -#include -typedef unsigned long CARD32; -typedef unsigned short CARD16; -typedef short INT16; -typedef unsigned char CARD8; -typedef int SOCKET; - -#endif - -#include "rfbproto.h" - -static bool keep_alive; -static bool client_connected; - -#define BX_RFB_PORT_MIN 5900 -#define BX_RFB_PORT_MAX 5949 -static unsigned short rfbPort; - -// Headerbar stuff -unsigned rfbBitmapCount = 0; -struct { - char *bmap; - unsigned xdim; - unsigned ydim; -} rfbBitmaps[BX_MAX_PIXMAPS]; - -unsigned rfbHeaderbarBitmapCount = 0; -struct { - unsigned int index; - unsigned int xorigin; - unsigned int yorigin; - unsigned int alignment; - void (*f)(void); -} rfbHeaderbarBitmaps[BX_MAX_HEADERBAR_ENTRIES]; - -//Keyboard stuff -#define KEYBOARD true -#define MOUSE false -#define MAX_KEY_EVENTS 512 -struct { - bool type; - int key; - int down; - int x; - int y; -} rfbKeyboardEvent[MAX_KEY_EVENTS]; -static unsigned long rfbKeyboardEvents = 0; -static bool bKeyboardInUse = false; - -// Misc Stuff -struct { - unsigned int x; - unsigned int y; - unsigned int width; - unsigned int height; - bool updated; -} rfbUpdateRegion; - -static char *rfbScreen; -static char rfbPallet[256]; - -static long rfbDimensionX, rfbDimensionY; -static long rfbStretchedX, rfbStretchedY; -static long rfbHeaderbarY; -static long rfbTileX = 0; -static long rfbTileY = 0; -static unsigned long rfbCursorX = 0; -static unsigned long rfbCursorY = 0; -static unsigned long rfbOriginLeft = 0; -static unsigned long rfbOriginRight = 0; - -static unsigned int text_rows=25, text_cols=80; -static unsigned int font_height=16, font_width=8; - -//static unsigned long ServerThread = 0; -//static unsigned long ServerThreadID = 0; - -static SOCKET sGlobal; - -void ServerThreadInit(void *indata); -void HandleRfbClient(SOCKET sClient); -int ReadExact(int sock, char *buf, int len); -int WriteExact(int sock, char *buf, int len); -void DrawBitmap(int x, int y, int width, int height, char *bmap, char color, bool update_client); -void DrawChar(int x, int y, int width, int height, int fonty, char *bmap, char color); -void UpdateScreen(unsigned char *newBits, int x, int y, int width, int height, bool update_client); -void SendUpdate(int x, int y, int width, int height); -void StartThread(); -void rfbKeyPressed(Bit32u key, int press_release); -void rfbMouseMove(int x, int y, int bmask); -void DrawColorPallet(); - -static const rfbPixelFormat BGR233Format = { - 8, 8, 1, 1, 7, 7, 3, 0, 3, 6 -}; - -// Set this for the endian of your machine. 0 = big, 1 = little -static const int rfbEndianTest = 1; - -#define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) -#define Swap32(l) (((l) >> 24) | (((l) & 0x00ff0000) >> 8) | (((l) & 0x0000ff00) << 8) | ((l) << 24)) -#define Swap16IfLE(s) (*(const char *)&rfbEndianTest ? Swap16(s) : (s)) -#define Swap32IfLE(l) (*(const char *)&rfbEndianTest ? Swap32(l) : (l)) -#define PF_EQ(x,y) ((x.bitsPerPixel == y.bitsPerPixel) && (x.depth == y.depth) && (x.trueColour == y.trueColour) && ((x.bigEndian == y.bigEndian) || (x.bitsPerPixel == 8)) && (!x.trueColour || ((x.redMax == y.redMax) && (x.greenMax == y.greenMax) && (x.blueMax == y.blueMax) && (x.redShift == y.redShift) && (x.greenShift == y.greenShift) && (x.blueShift == y.blueShift)))) - -// This file defines stubs for the GUI interface, which is a -// place to start if you want to port bochs to a platform, for -// which there is no support for your native GUI, or if you want to compile -// bochs without any native GUI support (no output window or -// keyboard input will be possible). -// Look in 'x.cc', 'beos.cc', and 'win32.cc' for specific -// implementations of this interface. -Kevin - - -// ::SPECIFIC_INIT() -// -// Called from gui.cc, once upon program startup, to allow for the -// specific GUI code (X11, BeOS, ...) to be initialized. -// -// argc, argv: not used right now, but the intention is to pass native GUI -// specific options from the command line. (X11 options, BeOS options,...) -// -// tilewidth, tileheight: for optimization, graphics_tile_update() passes -// only updated regions of the screen to the gui code to be redrawn. -// These define the dimensions of a region (tile). -// headerbar_y: A headerbar (toolbar) is display on the top of the -// VGA window, showing floppy status, and other information. It -// always assumes the width of the current VGA mode width, but -// it's height is defined by this parameter. - -void bx_rfb_gui_c::specific_init(int argc, char **argv, unsigned tilewidth, unsigned tileheight, unsigned headerbar_y) -{ - unsigned char fc, vc; - - put("RFB"); - UNUSED(bochs_icon_bits); - - // the ask menu doesn't work on the client side - io->set_log_action(LOGLEV_PANIC, ACT_FATAL); - - rfbHeaderbarY = headerbar_y; - rfbDimensionX = 640; - rfbDimensionY = 480 + rfbHeaderbarY; - rfbStretchedX = rfbDimensionX; - rfbStretchedY = rfbDimensionY; - rfbTileX = tilewidth; - rfbTileY = tileheight; - - for(int i = 0; i < 256; i++) { - for(int j = 0; j < 16; j++) { - vc = bx_vgafont[i].data[j]; - fc = 0; - for (int b = 0; b < 8; b++) { - fc |= (vc & 0x01) << (7 - b); - vc >>= 1; - } - vga_charmap[i*32+j] = fc; - } - } - - rfbScreen = (char *)malloc(rfbDimensionX * rfbDimensionY); - memset(&rfbPallet, 0, sizeof(rfbPallet)); - rfbPallet[63] = (char)0xFF; - - rfbUpdateRegion.x = rfbDimensionX; - rfbUpdateRegion.y = rfbDimensionY; - rfbUpdateRegion.width = 0; - rfbUpdateRegion.height = 0; - rfbUpdateRegion.updated = false; - - keep_alive = true; - client_connected = false; - StartThread(); - -#ifdef WIN32 - Sleep(1000); - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); -#endif - if (bx_options.Oprivate_colormap->get ()) { - BX_ERROR(( "private_colormap option ignored." )); - } - int counter = 30; - while ((!client_connected) && (counter--)) { -#ifdef WIN32 - Sleep(1000); -#else - sleep(1); -#endif - } - if (counter < 0) BX_PANIC(("timeout! no client present")); -} - -bool InitWinsock() -{ -#ifdef WIN32 - WSADATA wsaData; - if(WSAStartup(MAKEWORD(1,1), &wsaData) != 0) return false; -#endif - return true; -} - -bool StopWinsock() -{ -#ifdef WIN32 - WSACleanup(); -#endif - return true; -} - -void ServerThreadInit(void *indata) -{ - SOCKET sServer; - SOCKET sClient; - struct sockaddr_in sai; - unsigned int sai_size; - int port_ok = 0; - -#ifdef WIN32 - SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE); -#endif - if(!InitWinsock()) { - BX_PANIC(( "could not initialize winsock.")); - goto end_of_thread; - } - - sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if(sServer == -1) { - BX_PANIC(( "could not create socket." )); - goto end_of_thread; - } - for (rfbPort = BX_RFB_PORT_MIN; rfbPort <= BX_RFB_PORT_MAX; rfbPort++) { - sai.sin_addr.s_addr = INADDR_ANY; - sai.sin_family = AF_INET; - sai.sin_port = htons(rfbPort); - BX_INFO (("Trying port %d", rfbPort)); - if(bind(sServer, (struct sockaddr *)&sai, sizeof(sai)) == -1) { - BX_INFO(( "Could not bind socket.")); - continue; - } - if(listen(sServer, SOMAXCONN) == -1) { - BX_INFO(( "Could not listen on socket.")); - continue; - } - // success - port_ok = 1; - break; - } - if (!port_ok) { - BX_PANIC (("RFB could not bind any port between %d and %d\n", - BX_RFB_PORT_MIN, - BX_RFB_PORT_MAX)); - goto end_of_thread; - } - BX_INFO (("listening for connections on port %i", rfbPort)); - fprintf (stderr, "RFB: listening for connections on port %i\n", rfbPort); - sai_size = sizeof(sai); - while(keep_alive) { - sClient = accept(sServer, (struct sockaddr *)&sai, (socklen_t*)&sai_size); - if(sClient != -1) { - HandleRfbClient(sClient); - sGlobal = -1; - close(sClient); - } else { - close(sClient); - } - } - -end_of_thread: - StopWinsock(); -} - -void HandleRfbClient(SOCKET sClient) -{ - char rfbName[] = "Bochs-RFB"; - rfbProtocolVersionMsg pv; - int one = 1; - CARD32 auth; - rfbClientInitMsg cim; - rfbServerInitMsg sim; - - client_connected = true; - setsockopt(sClient, IPPROTO_TCP, TCP_NODELAY, (const char *)&one, sizeof(one)); - fprintf(stderr, "# RFB: accepted client connection.\n"); - sprintf(pv, rfbProtocolVersionFormat, rfbProtocolMajorVersion, rfbProtocolMinorVersion); - - if(WriteExact(sClient, pv, sz_rfbProtocolVersionMsg) < 0) { - fprintf(stderr, "# ERROR: RFB: could not send protocol version.\n"); - return; - } - if(ReadExact(sClient, pv, sz_rfbProtocolVersionMsg) < 0) { - fprintf(stderr, "# ERROR: RFB: could not recieve client protocol version.\n"); - return; - } - - auth = Swap32IfLE(rfbNoAuth); - if(WriteExact(sClient, (char *)&auth, sizeof(auth)) < 0) { - fprintf(stderr, "# ERROR: RFB: could not send authorization method.\n"); - return; - } - - if(ReadExact(sClient, (char *)&cim, sz_rfbClientInitMsg) < 0) { - fprintf(stderr, "# ERROR: RFB: could not recieve client initialization message.\n"); - return; - } - - sim.framebufferWidth = Swap16IfLE((short)rfbDimensionX); - sim.framebufferHeight = Swap16IfLE((short)rfbDimensionY); - sim.format = BGR233Format; - sim.format.redMax = Swap16IfLE(sim.format.redMax); - sim.format.greenMax = Swap16IfLE(sim.format.greenMax); - sim.format.blueMax = Swap16IfLE(sim.format.blueMax); - sim.nameLength = strlen(rfbName); - sim.nameLength = Swap32IfLE(sim.nameLength); - if(WriteExact(sClient, (char *)&sim, sz_rfbServerInitMsg) < 0) { - fprintf(stderr, "# ERROR: RFB: could send server initialization message.\n"); - return; - } - if(WriteExact(sClient, rfbName, strlen(rfbName)) < 0) { - fprintf(stderr, "# ERROR: RFB: could not send server name.\n"); - return; - } - - sGlobal = sClient; - while(keep_alive) { - CARD8 msgType; - int n; - - if((n = recv(sClient, (char *)&msgType, 1, MSG_PEEK)) <= 0) { - if(n == 0) { - fprintf(stderr, "# RFB: client closed connection.\n"); - } else { - fprintf(stderr, "# RFB: error recieving data.\n"); - } - return; - } - - switch(msgType) { - case rfbSetPixelFormat: - { - rfbSetPixelFormatMsg spf; - ReadExact(sClient, (char *)&spf, sizeof(rfbSetPixelFormatMsg)); - - spf.format.bitsPerPixel = spf.format.bitsPerPixel; - spf.format.depth = spf.format.depth; - spf.format.trueColour = (spf.format.trueColour ? 1 : 0); - spf.format.bigEndian = (spf.format.bigEndian ? 1 : 0); - spf.format.redMax = Swap16IfLE(spf.format.redMax); - spf.format.greenMax = Swap16IfLE(spf.format.greenMax); - spf.format.blueMax = Swap16IfLE(spf.format.blueMax); - spf.format.redShift = spf.format.redShift; - spf.format.greenShift = spf.format.greenShift; - spf.format.blueShift = spf.format.blueShift; - - if (!PF_EQ(spf.format, BGR233Format)) { - fprintf(stderr,"# ERROR: RFB: client has wrong pixel format\n"); - //return; - } - break; - } - case rfbFixColourMapEntries: - { - rfbFixColourMapEntriesMsg fcme; - ReadExact(sClient, (char *)&fcme, sizeof(rfbFixColourMapEntriesMsg)); - break; - } - case rfbSetEncodings: - { - rfbSetEncodingsMsg se; - int i; - CARD32 enc; - ReadExact(sClient, (char *)&se, sizeof(rfbSetEncodingsMsg)); - se.nEncodings = Swap16IfLE(se.nEncodings); - for(i = 0; i < se.nEncodings; i++) { - if((n = ReadExact(sClient, (char *)&enc, sizeof(CARD32))) <= 0) { - if(n == 0) { - fprintf(stderr, "# RFB: client closed connection.\n"); - } else { - fprintf(stderr, "# RFB: error recieving data.\n"); - } - return; - } - } - break; - } - case rfbFramebufferUpdateRequest: - { - rfbFramebufferUpdateRequestMsg fur; - - ReadExact(sClient, (char *)&fur, sizeof(rfbFramebufferUpdateRequestMsg)); - if(!fur.incremental) { - rfbUpdateRegion.x = 0; - rfbUpdateRegion.y = 0; - rfbUpdateRegion.width = rfbDimensionX; - rfbUpdateRegion.height = rfbDimensionY; - rfbUpdateRegion.updated = true; - } //else { - // if(fur.x < rfbUpdateRegion.x) rfbUpdateRegion.x = fur.x; - // if(fur.y < rfbUpdateRegion.x) rfbUpdateRegion.y = fur.y; - // if(((fur.x + fur.w) - rfbUpdateRegion.x) > rfbUpdateRegion.width) rfbUpdateRegion.width = ((fur.x + fur.w) - rfbUpdateRegion.x); - // if(((fur.y + fur.h) - rfbUpdateRegion.y) > rfbUpdateRegion.height) rfbUpdateRegion.height = ((fur.y + fur.h) - rfbUpdateRegion.y); - //} - //rfbUpdateRegion.updated = true; - break; - } - case rfbKeyEvent: - { - rfbKeyEventMsg ke; - ReadExact(sClient, (char *)&ke, sizeof(rfbKeyEventMsg)); - ke.key = Swap32IfLE(ke.key); - while(bKeyboardInUse); - bKeyboardInUse = true; - if (rfbKeyboardEvents >= MAX_KEY_EVENTS) break; - rfbKeyboardEvent[rfbKeyboardEvents].type = KEYBOARD; - rfbKeyboardEvent[rfbKeyboardEvents].key = ke.key; - rfbKeyboardEvent[rfbKeyboardEvents].down = ke.down; - rfbKeyboardEvents++; - bKeyboardInUse = false; - break; - } - case rfbPointerEvent: - { - rfbPointerEventMsg pe; - ReadExact(sClient, (char *)&pe, sizeof(rfbPointerEventMsg)); - while(bKeyboardInUse); - bKeyboardInUse = true; - if (rfbKeyboardEvents >= MAX_KEY_EVENTS) break; - rfbKeyboardEvent[rfbKeyboardEvents].type = MOUSE; - rfbKeyboardEvent[rfbKeyboardEvents].x = Swap16IfLE(pe.x); - rfbKeyboardEvent[rfbKeyboardEvents].y = Swap16IfLE(pe.y); - rfbKeyboardEvent[rfbKeyboardEvents].down = pe.buttonMask; - rfbKeyboardEvents++; - bKeyboardInUse = false; - break; - } - case rfbClientCutText: - { - rfbClientCutTextMsg cct; - ReadExact(sClient, (char *)&cct, sizeof(rfbClientCutTextMsg)); - break; - } - } - } -} -// ::HANDLE_EVENTS() -// -// Called periodically (vga_update_interval in .bochsrc) so the -// the gui code can poll for keyboard, mouse, and other -// relevant events. - -void bx_rfb_gui_c::handle_events(void) -{ - unsigned int i = 0; - while(bKeyboardInUse); - bKeyboardInUse = true; - if(rfbKeyboardEvents > 0) { - for(i = 0; i < rfbKeyboardEvents; i++) { - if(rfbKeyboardEvent[i].type == KEYBOARD) { - rfbKeyPressed(rfbKeyboardEvent[i].key, rfbKeyboardEvent[i].down); - } else { //type == MOUSE; - rfbMouseMove(rfbKeyboardEvent[i].x, rfbKeyboardEvent[i].y, rfbKeyboardEvent[i].down); - } - } - rfbKeyboardEvents = 0; - } - bKeyboardInUse = false; - - if(rfbUpdateRegion.updated) { - SendUpdate(rfbUpdateRegion.x, rfbUpdateRegion.y, rfbUpdateRegion.width, rfbUpdateRegion.height); - rfbUpdateRegion.x = rfbDimensionX; - rfbUpdateRegion.y = rfbDimensionY; - rfbUpdateRegion.width = 0; - rfbUpdateRegion.height = 0; - } - rfbUpdateRegion.updated = false; -} - - -// ::FLUSH() -// -// Called periodically, requesting that the gui code flush all pending -// screen update requests. - -void bx_rfb_gui_c::flush(void) -{ -} - - -// ::CLEAR_SCREEN() -// -// Called to request that the VGA region is cleared. Don't -// clear the area that defines the headerbar. -void bx_rfb_gui_c::clear_screen(void) -{ - memset(&rfbScreen[rfbDimensionX * rfbHeaderbarY], 0, rfbDimensionX * (rfbDimensionY - rfbHeaderbarY)); -} - - - -// ::TEXT_UPDATE() -// -// Called in a VGA text mode, to update the screen with -// new content. -// -// old_text: array of character/attributes making up the contents -// of the screen from the last call. See below -// new_text: array of character/attributes making up the current -// contents, which should now be displayed. See below -// -// format of old_text & new_text: each is 4000 bytes long. -// This represents 80 characters wide by 25 high, with -// each character being 2 bytes. The first by is the -// character value, the second is the attribute byte. -// I currently don't handle the attribute byte. -// -// cursor_x: new x location of cursor -// cursor_y: new y location of cursor - -void bx_rfb_gui_c::text_update(Bit8u *old_text, Bit8u *new_text, unsigned long cursor_x, unsigned long cursor_y, bx_vga_tminfo_t tm_info, unsigned nrows) -{ - unsigned char *old_line, *new_line; - unsigned char cAttr, cChar; - unsigned int curs, hchars, offset, rows, x, y, xc, yc; - bx_bool force_update=0; - - UNUSED(nrows); - - if(charmap_updated) { - force_update = 1; - charmap_updated = 0; - } - - // first invalidate character at previous and new cursor location - if ( (rfbCursorY < text_rows) && (rfbCursorX < text_cols) ) { - curs = rfbCursorY * tm_info.line_offset + rfbCursorX * 2; - old_text[curs] = ~new_text[curs]; - } - if((tm_info.cs_start <= tm_info.cs_end) && (tm_info.cs_start < font_height) && - (cursor_y < text_rows) && (cursor_x < text_cols)) { - curs = cursor_y * tm_info.line_offset + cursor_x * 2; - old_text[curs] = ~new_text[curs]; - } else { - curs = 0xffff; - } - - rows = text_rows; - y = 0; - do { - hchars = text_cols; - new_line = new_text; - old_line = old_text; - offset = y * tm_info.line_offset; - yc = y * font_height + rfbHeaderbarY; - x = 0; - do { - if (force_update || (old_text[0] != new_text[0]) - || (old_text[1] != new_text[1])) { - cChar = new_text[0]; - cAttr = new_text[1]; - xc = x * 8; - DrawChar(xc, yc, 8, font_height, 0, (char *)&vga_charmap[cChar<<5], cAttr); - if(yc < rfbUpdateRegion.y) rfbUpdateRegion.y = yc; - if((yc + font_height - rfbUpdateRegion.y) > rfbUpdateRegion.height) rfbUpdateRegion.height = (yc + font_height - rfbUpdateRegion.y); - if(xc < rfbUpdateRegion.x) rfbUpdateRegion.x = xc; - if((xc + 8 - rfbUpdateRegion.x) > rfbUpdateRegion.width) rfbUpdateRegion.width = (xc + 8 - rfbUpdateRegion.x); - rfbUpdateRegion.updated = true; - if (offset == curs) { - cAttr = ((cAttr >> 4) & 0xF) + ((cAttr & 0xF) << 4); - DrawChar(xc, yc + tm_info.cs_start, 8, tm_info.cs_end - tm_info.cs_start + 1, - tm_info.cs_start, (char *)&vga_charmap[cChar<<5], cAttr); - } - } - x++; - new_text+=2; - old_text+=2; - offset+=2; - } while (--hchars); - y++; - new_text = new_line + tm_info.line_offset; - old_text = old_line + tm_info.line_offset; - } while (--rows); - - rfbCursorX = cursor_x; - rfbCursorY = cursor_y; -} - - int -bx_rfb_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes) -{ - return 0; -} - - int -bx_rfb_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len) -{ - return 0; -} - - -// ::PALETTE_CHANGE() -// -// Allocate a color in the native GUI, for this color, and put -// it in the colormap location 'index'. -// returns: 0=no screen update needed (color map change has direct effect) -// 1=screen updated needed (redraw using current colormap) - -bx_bool bx_rfb_gui_c::palette_change(unsigned index, unsigned red, unsigned green, unsigned blue) -{ - rfbPallet[index] = (((red * 7 + 127) / 255) << 0) | (((green * 7 + 127) / 255) << 3) | (((blue * 3 + 127) / 255) << 6); - return(1); -} - - -// ::GRAPHICS_TILE_UPDATE() -// -// Called to request that a tile of graphics be drawn to the -// screen, since info in this region has changed. -// -// tile: array of 8bit values representing a block of pixels with -// dimension equal to the 'tilewidth' & 'tileheight' parameters to -// ::specific_init(). Each value specifies an index into the -// array of colors you allocated for ::palette_change() -// x0: x origin of tile -// y0: y origin of tile -// -// note: origin of tile and of window based on (0,0) being in the upper -// left of the window. -void bx_rfb_gui_c::graphics_tile_update(Bit8u *tile, unsigned x0, unsigned y0) -{ - UpdateScreen(tile, x0, y0 + rfbHeaderbarY, rfbTileX, rfbTileY, false); - if(x0 < rfbUpdateRegion.x) rfbUpdateRegion.x = x0; - if((y0 + rfbHeaderbarY) < rfbUpdateRegion.y) rfbUpdateRegion.y = y0 + rfbHeaderbarY; - if(((y0 + rfbHeaderbarY + rfbTileY) - rfbUpdateRegion.y) > rfbUpdateRegion.height) rfbUpdateRegion.height = ((y0 + rfbHeaderbarY + rfbTileY) - rfbUpdateRegion.y); - if(((x0 + rfbTileX) - rfbUpdateRegion.x) > rfbUpdateRegion.width) rfbUpdateRegion.width = ((x0 + rfbTileX) - rfbUpdateRegion.x); - rfbUpdateRegion.updated = true; -} - - - -// ::DIMENSION_UPDATE() -// -// Called when the VGA mode changes it's X,Y dimensions. -// Resize the window to this size, but you need to add on -// the height of the headerbar to the Y value. -// -// x: new VGA x size -// y: new VGA y size (add headerbar_y parameter from ::specific_init(). -// fheight: new VGA character height in text mode -// fwidth : new VGA character width in text mode -// bpp : bits per pixel in graphics mode - - void -bx_rfb_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, unsigned fwidth, unsigned bpp) -{ - if (bpp > 8) { - BX_PANIC(("%d bpp graphics mode not supported yet", bpp)); - } - if (fheight > 0) { - font_height = fheight; - font_width = fwidth; - text_cols = x / fwidth; - text_rows = y / fheight; - } else { - if ((x > 640) || (y > 480)) { - BX_PANIC(("dimension_update(): RFB doesn't support graphics modes > 640x480 (%dx%d)", x, y)); - } - } -} - - -// ::CREATE_BITMAP() -// -// Create a monochrome bitmap of size 'xdim' by 'ydim', which will -// be drawn in the headerbar. Return an integer ID to the bitmap, -// with which the bitmap can be referenced later. -// -// bmap: packed 8 pixels-per-byte bitmap. The pixel order is: -// bit0 is the left most pixel, bit7 is the right most pixel. -// xdim: x dimension of bitmap -// ydim: y dimension of bitmap - -unsigned bx_rfb_gui_c::create_bitmap(const unsigned char *bmap, unsigned xdim, unsigned ydim) -{ - if(rfbBitmapCount >= BX_MAX_PIXMAPS) { - fprintf(stderr, "# RFB: too many pixmaps.\n"); - return 0; - } - rfbBitmaps[rfbBitmapCount].bmap = (char *)malloc((xdim * ydim) / 8); - rfbBitmaps[rfbBitmapCount].xdim = xdim; - rfbBitmaps[rfbBitmapCount].ydim = ydim; - memcpy(rfbBitmaps[rfbBitmapCount].bmap, bmap, (xdim * ydim) / 8); - - rfbBitmapCount++; - return(rfbBitmapCount - 1); -} - - -// ::HEADERBAR_BITMAP() -// -// Called to install a bitmap in the bochs headerbar (toolbar). -// -// bmap_id: will correspond to an ID returned from -// ::create_bitmap(). 'alignment' is either BX_GRAVITY_LEFT -// or BX_GRAVITY_RIGHT, meaning install the bitmap in the next -// available leftmost or rightmost space. -// alignment: is either BX_GRAVITY_LEFT or BX_GRAVITY_RIGHT, -// meaning install the bitmap in the next -// available leftmost or rightmost space. -// f: a 'C' function pointer to callback when the mouse is clicked in -// the boundaries of this bitmap. - -unsigned bx_rfb_gui_c::headerbar_bitmap(unsigned bmap_id, unsigned alignment, void (*f)(void)) -{ - int hb_index; - - if((rfbHeaderbarBitmapCount + 1) > BX_MAX_HEADERBAR_ENTRIES) { - return 0; - } - - rfbHeaderbarBitmapCount++; - hb_index = rfbHeaderbarBitmapCount - 1; - rfbHeaderbarBitmaps[hb_index].index = bmap_id; - rfbHeaderbarBitmaps[hb_index].alignment = alignment; - rfbHeaderbarBitmaps[hb_index].f = f; - if (alignment == BX_GRAVITY_LEFT) { - rfbHeaderbarBitmaps[hb_index].xorigin = rfbOriginLeft; - rfbHeaderbarBitmaps[hb_index].yorigin = 0; - rfbOriginLeft += rfbBitmaps[bmap_id].xdim; - } else { // BX_GRAVITY_RIGHT - rfbOriginRight += rfbBitmaps[bmap_id].xdim; - rfbHeaderbarBitmaps[hb_index].xorigin = rfbOriginRight; - rfbHeaderbarBitmaps[hb_index].yorigin = 0; - } - return hb_index; -} - - -// ::SHOW_HEADERBAR() -// -// Show (redraw) the current headerbar, which is composed of -// currently installed bitmaps. - -void bx_rfb_gui_c::show_headerbar(void) -{ - char *newBits; - unsigned int i, xorigin; - - newBits = (char *)malloc(rfbDimensionX * rfbHeaderbarY); - memset(newBits, 0, (rfbDimensionX * rfbHeaderbarY)); - DrawBitmap(0, 0, rfbDimensionX, rfbHeaderbarY, newBits, (char)0xf0, false); - for(i = 0; i < rfbHeaderbarBitmapCount; i++) { - if(rfbHeaderbarBitmaps[i].alignment == BX_GRAVITY_LEFT) { - xorigin = rfbHeaderbarBitmaps[i].xorigin; - } else { - xorigin = rfbDimensionX - rfbHeaderbarBitmaps[i].xorigin; - } - DrawBitmap(xorigin, 0, rfbBitmaps[rfbHeaderbarBitmaps[i].index].xdim, rfbBitmaps[rfbHeaderbarBitmaps[i].index].ydim, rfbBitmaps[rfbHeaderbarBitmaps[i].index].bmap, (char)0xf0, false); - } - free(newBits); -} - - -// ::REPLACE_BITMAP() -// -// Replace the bitmap installed in the headerbar ID slot 'hbar_id', -// with the one specified by 'bmap_id'. 'bmap_id' will have -// been generated by ::create_bitmap(). The old and new bitmap -// must be of the same size. This allows the bitmap the user -// sees to change, when some action occurs. For example when -// the user presses on the floppy icon, it then displays -// the ejected status. -// -// hbar_id: headerbar slot ID -// bmap_id: bitmap ID - -void bx_rfb_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id) -{ - rfbHeaderbarBitmaps[hbar_id].index = bmap_id; -} - - -// ::EXIT() -// -// Called before bochs terminates, to allow for a graceful -// exit from the native GUI mechanism. -void bx_rfb_gui_c::exit(void) -{ - unsigned int i; - keep_alive = false; - StopWinsock(); - free(rfbScreen); - for(i = 0; i < rfbBitmapCount; i++) { - free(rfbBitmaps[i].bmap); - } - fprintf(stderr, "# RFB: bx_rfb_gui_c::exit()\n"); -} - -/* -* ReadExact reads an exact number of bytes on a TCP socket. Returns 1 if -* those bytes have been read, 0 if the other end has closed, or -1 if an error -* occurred (errno is set to ETIMEDOUT if it timed out). -*/ - -int ReadExact(int sock, char *buf, int len) -{ - int n; - - while (len > 0) { - n = recv(sock, buf, len, 0); - if (n > 0) { - buf += n; - len -= n; - } else { - return n; - } - } - return 1; -} - -/* -* WriteExact writes an exact number of bytes on a TCP socket. Returns 1 if -* those bytes have been written, or -1 if an error occurred (errno is set to -* ETIMEDOUT if it timed out). -*/ - -int WriteExact(int sock, char *buf, int len) -{ - int n; - - while (len > 0) { - n = send(sock, buf, len,0); - - if (n > 0) { - buf += n; - len -= n; - } else if (n == 0) { - fprintf(stderr,"WriteExact: write returned 0?\n"); - return n; - } else { - return n; - } - } - return 1; -} - -void DrawBitmap(int x, int y, int width, int height, char *bmap, char color, bool update_client) -{ - int i; - unsigned char *newBits; - char fgcolor, bgcolor; - char vgaPallet[] = { (char)0x00, //Black - (char)0x01, //Dark Blue - (char)0x02, //Dark Green - (char)0x03, //Dark Cyan - (char)0x04, //Dark Red - (char)0x05, //Dark Magenta - (char)0x06, //Brown - (char)0x07, //Light Gray - (char)0x38, //Dark Gray - (char)0x09, //Light Blue - (char)0x12, //Green - (char)0x1B, //Cyan - (char)0x24, //Light Red - (char)0x2D, //Magenta - (char)0x36, //Yellow - (char)0x3F //White - }; - - bgcolor = vgaPallet[(color >> 4) & 0xF]; - fgcolor = vgaPallet[color & 0xF]; - newBits = (unsigned char *)malloc(width * height); - memset(newBits, 0, (width * height)); - for(i = 0; i < (width * height) / 8; i++) { - newBits[i * 8 + 0] = (bmap[i] & 0x01) ? fgcolor : bgcolor; - newBits[i * 8 + 1] = (bmap[i] & 0x02) ? fgcolor : bgcolor; - newBits[i * 8 + 2] = (bmap[i] & 0x04) ? fgcolor : bgcolor; - newBits[i * 8 + 3] = (bmap[i] & 0x08) ? fgcolor : bgcolor; - newBits[i * 8 + 4] = (bmap[i] & 0x10) ? fgcolor : bgcolor; - newBits[i * 8 + 5] = (bmap[i] & 0x20) ? fgcolor : bgcolor; - newBits[i * 8 + 6] = (bmap[i] & 0x40) ? fgcolor : bgcolor; - newBits[i * 8 + 7] = (bmap[i] & 0x80) ? fgcolor : bgcolor; - } - UpdateScreen(newBits, x, y, width, height, update_client); - //DrawColorPallet(); - free(newBits); -} - -void DrawChar(int x, int y, int width, int height, int fonty, char *bmap, char color) -{ - static unsigned char newBits[8 * 32]; - unsigned char mask; - int bytes = width * height; - char fgcolor, bgcolor; - char vgaPallet[] = { (char)0x00, //Black - (char)0x01, //Dark Blue - (char)0x02, //Dark Green - (char)0x03, //Dark Cyan - (char)0x04, //Dark Red - (char)0x05, //Dark Magenta - (char)0x06, //Brown - (char)0x07, //Light Gray - (char)0x38, //Dark Gray - (char)0x09, //Light Blue - (char)0x12, //Green - (char)0x1B, //Cyan - (char)0x24, //Light Red - (char)0x2D, //Magenta - (char)0x36, //Yellow - (char)0x3F //White - }; - - bgcolor = vgaPallet[(color >> 4) & 0xF]; - fgcolor = vgaPallet[color & 0xF]; - - for(int i = 0; i < bytes; i+=width) { - mask = 0x80; - for(int j = 0; j < width; j++) { - newBits[i + j] = (bmap[fonty] & mask) ? fgcolor : bgcolor; - mask >>= 1; - } - fonty++; - } - UpdateScreen(newBits, x, y, width, height, false); - //DrawColorPallet(); -} - -void DrawColorPallet() -{ - unsigned char bits[100]; - int x = 0, y = 0, c; - for(c = 0; c < 256; c++) { - memset(&bits, rfbPallet[c], 100); - UpdateScreen(bits, x, y, 10, 10, false); - x += 10; - if(x > 70) { - y += 10; - x = 0; - } - } -} - -void UpdateScreen(unsigned char *newBits, int x, int y, int width, int height, bool update_client) -{ - int i, c; - for(i = 0; i < height; i++) { - for(c = 0; c < width; c++) { - newBits[(i * width) + c] = rfbPallet[newBits[(i * width) + c]]; - } - memcpy(&rfbScreen[y * rfbDimensionX + x], &newBits[i * width], width); - y++; - } - if(update_client) { - if(sGlobal == -1) return; - rfbFramebufferUpdateMsg fum; - rfbFramebufferUpdateRectHeader furh; - fum.type = rfbFramebufferUpdate; - fum.nRects = Swap16IfLE(1); - WriteExact(sGlobal, (char *)&fum, sz_rfbFramebufferUpdateMsg); - furh.r.x = Swap16IfLE(x); - furh.r.y = Swap16IfLE((y - i)); - furh.r.w = Swap16IfLE((short)width); - furh.r.h = Swap16IfLE((short)height); - furh.encoding = Swap32IfLE(rfbEncodingRaw); - WriteExact(sGlobal, (char *)&furh, sz_rfbFramebufferUpdateRectHeader); - WriteExact(sGlobal, (char *)newBits, width * height); - } -} - -void SendUpdate(int x, int y, int width, int height) -{ - char *newBits; - int i; - - if(x < 0 || y < 0 || (x + width) > rfbDimensionX || (y + height) > rfbDimensionY) { - fprintf(stderr, "# RFB: Dimensions out of bounds. x=%i y=%i w=%i h=%i\n", x, y, width, height); - } - if(sGlobal != -1) { - rfbFramebufferUpdateMsg fum; - rfbFramebufferUpdateRectHeader furh; - - fum.type = rfbFramebufferUpdate; - fum.nRects = Swap16IfLE(1); - - furh.r.x = Swap16IfLE(x); - furh.r.y = Swap16IfLE(y); - furh.r.w = Swap16IfLE((short)width); - furh.r.h = Swap16IfLE((short)height); - furh.encoding = Swap32IfLE(rfbEncodingRaw); - - newBits = (char *)malloc(width * height); - for(i = 0; i < height; i++) { - memcpy(&newBits[i * width], &rfbScreen[y * rfbDimensionX + x], width); - y++; - } - - WriteExact(sGlobal, (char *)&fum, sz_rfbFramebufferUpdateMsg); - WriteExact(sGlobal, (char *)&furh, sz_rfbFramebufferUpdateRectHeader); - WriteExact(sGlobal, (char *)newBits, width * height); - - free(newBits); - } -} - -void StartThread() -{ -#ifdef WIN32 - _beginthread(ServerThreadInit, 0, NULL); -#else - pthread_t thread; - pthread_create(&thread, NULL, (void *(*)(void *))&ServerThreadInit, NULL); -#endif -} - -/***********************/ -/* Keyboard Definitons */ -/* And */ -/* Functions */ -/***********************/ - -#define XK_space 0x020 -#define XK_asciitilde 0x07e - -#define XK_dead_grave 0xFE50 -#define XK_dead_acute 0xFE51 -#define XK_dead_circumflex 0xFE52 -#define XK_dead_tilde 0xFE53 - -#define XK_BackSpace 0xFF08 -#define XK_Tab 0xFF09 -#define XK_Linefeed 0xFF0A -#define XK_Clear 0xFF0B -#define XK_Return 0xFF0D -#define XK_Pause 0xFF13 -#define XK_Scroll_Lock 0xFF14 -#define XK_Sys_Req 0xFF15 -#define XK_Escape 0xFF1B - -#define XK_Delete 0xFFFF - -#define XK_Home 0xFF50 -#define XK_Left 0xFF51 -#define XK_Up 0xFF52 -#define XK_Right 0xFF53 -#define XK_Down 0xFF54 -#define XK_Page_Up 0xFF55 -#define XK_Page_Down 0xFF56 -#define XK_End 0xFF57 -#define XK_Begin 0xFF58 - -#define XK_Select 0xFF60 -#define XK_Print 0xFF61 -#define XK_Execute 0xFF62 -#define XK_Insert 0xFF63 - -#define XK_Cancel 0xFF69 -#define XK_Help 0xFF6A -#define XK_Break 0xFF6B -#define XK_Num_Lock 0xFF7F - -#define XK_KP_Space 0xFF80 -#define XK_KP_Tab 0xFF89 -#define XK_KP_Enter 0xFF8D - -#define XK_KP_Home 0xFF95 -#define XK_KP_Left 0xFF96 -#define XK_KP_Up 0xFF97 -#define XK_KP_Right 0xFF98 -#define XK_KP_Down 0xFF99 -#define XK_KP_Prior 0xFF9A -#define XK_KP_Page_Up 0xFF9A -#define XK_KP_Next 0xFF9B -#define XK_KP_Page_Down 0xFF9B -#define XK_KP_End 0xFF9C -#define XK_KP_Begin 0xFF9D -#define XK_KP_Insert 0xFF9E -#define XK_KP_Delete 0xFF9F -#define XK_KP_Equal 0xFFBD -#define XK_KP_Multiply 0xFFAA -#define XK_KP_Add 0xFFAB -#define XK_KP_Separator 0xFFAC -#define XK_KP_Subtract 0xFFAD -#define XK_KP_Decimal 0xFFAE -#define XK_KP_Divide 0xFFAF - -#define XK_KP_F1 0xFF91 -#define XK_KP_F2 0xFF92 -#define XK_KP_F3 0xFF93 -#define XK_KP_F4 0xFF94 - -#define XK_KP_0 0xFFB0 -#define XK_KP_1 0xFFB1 -#define XK_KP_2 0xFFB2 -#define XK_KP_3 0xFFB3 -#define XK_KP_4 0xFFB4 -#define XK_KP_5 0xFFB5 -#define XK_KP_6 0xFFB6 -#define XK_KP_7 0xFFB7 -#define XK_KP_8 0xFFB8 -#define XK_KP_9 0xFFB9 - -#define XK_F1 0xFFBE -#define XK_F2 0xFFBF -#define XK_F3 0xFFC0 -#define XK_F4 0xFFC1 -#define XK_F5 0xFFC2 -#define XK_F6 0xFFC3 -#define XK_F7 0xFFC4 -#define XK_F8 0xFFC5 -#define XK_F9 0xFFC6 -#define XK_F10 0xFFC7 -#define XK_F11 0xFFC8 -#define XK_F12 0xFFC9 -#define XK_F13 0xFFCA -#define XK_F14 0xFFCB -#define XK_F15 0xFFCC -#define XK_F16 0xFFCD -#define XK_F17 0xFFCE -#define XK_F18 0xFFCF -#define XK_F19 0xFFD0 -#define XK_F20 0xFFD1 -#define XK_F21 0xFFD2 -#define XK_F22 0xFFD3 -#define XK_F23 0xFFD4 -#define XK_F24 0xFFD5 - - -#define XK_Shift_L 0xFFE1 -#define XK_Shift_R 0xFFE2 -#define XK_Control_L 0xFFE3 -#define XK_Control_R 0xFFE4 -#define XK_Caps_Lock 0xFFE5 -#define XK_Shift_Lock 0xFFE6 -#define XK_Meta_L 0xFFE7 -#define XK_Meta_R 0xFFE8 -#define XK_Alt_L 0xFFE9 -#define XK_Alt_R 0xFFEA - -Bit32u rfb_ascii_to_key_event[0x5f] = { - // !"#$%&' - BX_KEY_SPACE, - BX_KEY_1, - BX_KEY_SINGLE_QUOTE, - BX_KEY_3, - BX_KEY_4, - BX_KEY_5, - BX_KEY_7, - BX_KEY_SINGLE_QUOTE, - - // ()*+,-./ - BX_KEY_9, - BX_KEY_0, - BX_KEY_8, - BX_KEY_EQUALS, - BX_KEY_COMMA, - BX_KEY_MINUS, - BX_KEY_PERIOD, - BX_KEY_SLASH, - - // 01234567 - BX_KEY_0, - BX_KEY_1, - BX_KEY_2, - BX_KEY_3, - BX_KEY_4, - BX_KEY_5, - BX_KEY_6, - BX_KEY_7, - - // 89:;<=>? - BX_KEY_8, - BX_KEY_9, - BX_KEY_SEMICOLON, - BX_KEY_SEMICOLON, - BX_KEY_COMMA, - BX_KEY_EQUALS, - BX_KEY_PERIOD, - BX_KEY_SLASH, - - // @ABCDEFG - BX_KEY_2, - BX_KEY_A, - BX_KEY_B, - BX_KEY_C, - BX_KEY_D, - BX_KEY_E, - BX_KEY_F, - BX_KEY_G, - - - // HIJKLMNO - BX_KEY_H, - BX_KEY_I, - BX_KEY_J, - BX_KEY_K, - BX_KEY_L, - BX_KEY_M, - BX_KEY_N, - BX_KEY_O, - - - // PQRSTUVW - BX_KEY_P, - BX_KEY_Q, - BX_KEY_R, - BX_KEY_S, - BX_KEY_T, - BX_KEY_U, - BX_KEY_V, - BX_KEY_W, - - // XYZ[\]^_ - BX_KEY_X, - BX_KEY_Y, - BX_KEY_Z, - BX_KEY_LEFT_BRACKET, - BX_KEY_BACKSLASH, - BX_KEY_RIGHT_BRACKET, - BX_KEY_6, - BX_KEY_MINUS, - - // `abcdefg - BX_KEY_GRAVE, - BX_KEY_A, - BX_KEY_B, - BX_KEY_C, - BX_KEY_D, - BX_KEY_E, - BX_KEY_F, - BX_KEY_G, - - // hijklmno - BX_KEY_H, - BX_KEY_I, - BX_KEY_J, - BX_KEY_K, - BX_KEY_L, - BX_KEY_M, - BX_KEY_N, - BX_KEY_O, - - // pqrstuvw - BX_KEY_P, - BX_KEY_Q, - BX_KEY_R, - BX_KEY_S, - BX_KEY_T, - BX_KEY_U, - BX_KEY_V, - BX_KEY_W, - - // xyz{|}~ - BX_KEY_X, - BX_KEY_Y, - BX_KEY_Z, - BX_KEY_LEFT_BRACKET, - BX_KEY_BACKSLASH, - BX_KEY_RIGHT_BRACKET, - BX_KEY_GRAVE - }; - -void rfbKeyPressed(Bit32u key, int press_release) -{ - Bit32u key_event; - - if((key >= XK_space) && (key <= XK_asciitilde)) { - key_event = rfb_ascii_to_key_event[key - XK_space]; - } else { - switch (key) { - case XK_KP_1: -#ifdef XK_KP_End - case XK_KP_End: -#endif - key_event = BX_KEY_KP_END; break; - - case XK_KP_2: -#ifdef XK_KP_Down - case XK_KP_Down: -#endif - key_event = BX_KEY_KP_DOWN; break; - - case XK_KP_3: -#ifdef XK_KP_Page_Down - case XK_KP_Page_Down: -#endif - key_event = BX_KEY_KP_PAGE_DOWN; break; - - case XK_KP_4: -#ifdef XK_KP_Left - case XK_KP_Left: -#endif - key_event = BX_KEY_KP_LEFT; break; - - case XK_KP_5: -#ifdef XK_KP_Begin - case XK_KP_Begin: -#endif - key_event = BX_KEY_KP_5; break; - - case XK_KP_6: -#ifdef XK_KP_Right - case XK_KP_Right: -#endif - key_event = BX_KEY_KP_RIGHT; break; - - case XK_KP_7: -#ifdef XK_KP_Home - case XK_KP_Home: -#endif - key_event = BX_KEY_KP_HOME; break; - - case XK_KP_8: -#ifdef XK_KP_Up - case XK_KP_Up: -#endif - key_event = BX_KEY_KP_UP; break; - - case XK_KP_9: -#ifdef XK_KP_Page_Up - case XK_KP_Page_Up: -#endif - key_event = BX_KEY_KP_PAGE_UP; break; - - case XK_KP_0: -#ifdef XK_KP_Insert - case XK_KP_Insert: -#endif - key_event = BX_KEY_KP_INSERT; break; - - case XK_KP_Decimal: -#ifdef XK_KP_Delete - case XK_KP_Delete: -#endif - key_event = BX_KEY_KP_DELETE; break; - -#ifdef XK_KP_Enter - case XK_KP_Enter: key_event = BX_KEY_KP_ENTER; break; -#endif - - case XK_KP_Subtract: key_event = BX_KEY_KP_SUBTRACT; break; - case XK_KP_Add: key_event = BX_KEY_KP_ADD; break; - - case XK_KP_Multiply: key_event = BX_KEY_KP_MULTIPLY; break; - case XK_KP_Divide: key_event = BX_KEY_KP_DIVIDE; break; - - - case XK_Up: key_event = BX_KEY_UP; break; - case XK_Down: key_event = BX_KEY_DOWN; break; - case XK_Left: key_event = BX_KEY_LEFT; break; - case XK_Right: key_event = BX_KEY_RIGHT; break; - - - case XK_Delete: key_event = BX_KEY_DELETE; break; - case XK_BackSpace: key_event = BX_KEY_BACKSPACE; break; - case XK_Tab: key_event = BX_KEY_TAB; break; -#ifdef XK_ISO_Left_Tab - case XK_ISO_Left_Tab: key_event = BX_KEY_TAB; break; -#endif - case XK_Return: key_event = BX_KEY_ENTER; break; - case XK_Escape: key_event = BX_KEY_ESC; break; - case XK_F1: key_event = BX_KEY_F1; break; - case XK_F2: key_event = BX_KEY_F2; break; - case XK_F3: key_event = BX_KEY_F3; break; - case XK_F4: key_event = BX_KEY_F4; break; - case XK_F5: key_event = BX_KEY_F5; break; - case XK_F6: key_event = BX_KEY_F6; break; - case XK_F7: key_event = BX_KEY_F7; break; - case XK_F8: key_event = BX_KEY_F8; break; - case XK_F9: key_event = BX_KEY_F9; break; - case XK_F10: key_event = BX_KEY_F10; break; - case XK_F11: key_event = BX_KEY_F11; break; - case XK_F12: key_event = BX_KEY_F12; break; - case XK_Control_L: key_event = BX_KEY_CTRL_L; break; -#ifdef XK_Control_R - case XK_Control_R: key_event = BX_KEY_CTRL_R; break; -#endif - case XK_Shift_L: key_event = BX_KEY_SHIFT_L; break; - case XK_Shift_R: key_event = BX_KEY_SHIFT_R; break; - case XK_Alt_L: key_event = BX_KEY_ALT_L; break; -#ifdef XK_Alt_R - case XK_Alt_R: key_event = BX_KEY_ALT_R; break; -#endif - case XK_Caps_Lock: key_event = BX_KEY_CAPS_LOCK; break; - case XK_Num_Lock: key_event = BX_KEY_NUM_LOCK; break; -#ifdef XK_Scroll_Lock - case XK_Scroll_Lock: key_event = BX_KEY_SCRL_LOCK; break; -#endif -#ifdef XK_Print - case XK_Print: key_event = BX_KEY_PRINT; break; -#endif -#ifdef XK_Pause - case XK_Pause: key_event = BX_KEY_PAUSE; break; -#endif - - case XK_Insert: key_event = BX_KEY_INSERT; break; - case XK_Home: key_event = BX_KEY_HOME; break; - case XK_End: key_event = BX_KEY_END; break; - case XK_Page_Up: key_event = BX_KEY_PAGE_UP; break; - case XK_Page_Down: key_event = BX_KEY_PAGE_DOWN; break; - - default: - BX_ERROR(("rfbKeyPress(): key %04x unhandled!", key)); - fprintf(stderr, "RFB: rfbKeyPress(): key %04x unhandled!\n", key); - return; - break; - } - } - - if (press_release) key_event |= BX_KEY_RELEASED; - DEV_kbd_gen_scancode(key_event); -} - -void rfbMouseMove(int x, int y, int bmask) -{ - static int oldx = -1; - static int oldy = -1; - int xorigin; - - if (oldx == oldy == -1) { - oldx = x; - oldy = y; - return; - } - if(y > rfbHeaderbarY) { - //DEV_mouse_motion(x, y - rfbHeaderbarY, buttons); - DEV_mouse_motion(x - oldx, oldy - y, bmask); - oldx = x; - oldy = y; - } else { - if (bmask == 1) { - for (unsigned i=0; i=xorigin) && (x<(xorigin+int(rfbBitmaps[rfbHeaderbarBitmaps[i].index].xdim))) ) { - rfbHeaderbarBitmaps[i].f(); - return; - } - } - } - } -} - - void -bx_rfb_gui_c::mouse_enabled_changed_specific (bx_bool val) -{ -} - -#endif /* if BX_WITH_RFB */ diff --git a/tools/ioemu/gui/rfb.h b/tools/ioemu/gui/rfb.h deleted file mode 100644 index 948ac8252f..0000000000 --- a/tools/ioemu/gui/rfb.h +++ /dev/null @@ -1,35 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: rfb.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// rfb.h -// This includes the rfb spec header, the port numbers, -// the CARD type definitions and various useful macros. -// - -#ifndef RFB_H__ -#define RFB_H__ - -// Define the CARD* types as used in X11/Xmd.h - -typedef unsigned long CARD32; -typedef unsigned short CARD16; -typedef short INT16; -typedef unsigned char CARD8; - -// Define the port number offsets -#define FLASH_PORT_OFFSET 5400 -#define INCOMING_PORT_OFFSET 5500 -#define HTTP_PORT_OFFSET 5800 // we don't use this in Venice -#define RFB_PORT_OFFSET 5900 - -#define _SIZEOF(x) sz_##x -#define SIZEOF(x) _SIZEOF(x) - -#define PORT_TO_DISPLAY(p) ( (p) - RFB_PORT_OFFSET ) -#define DISPLAY_TO_PORT(d) ( (d) + RFB_PORT_OFFSET ) - -#define EWOULDBLOCK WSAEWOULDBLOCK -#define ETIMEDOUT WSAETIMEDOUT - -#endif diff --git a/tools/ioemu/gui/rfbproto.h b/tools/ioemu/gui/rfbproto.h deleted file mode 100644 index a2be5f83c9..0000000000 --- a/tools/ioemu/gui/rfbproto.h +++ /dev/null @@ -1,675 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: rfbproto.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -/* - * Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - */ - -/* - * rfbproto.h - header file for the RFB protocol version 3.3 - * - * Uses types CARD for an n-bit unsigned integer, INT for an n-bit signed - * integer (for n = 8, 16 and 32). - * - * All multiple byte integers are in big endian (network) order (most - * significant byte first). Unless noted otherwise there is no special - * alignment of protocol structures. - * - * - * Once the initial handshaking is done, all messages start with a type byte, - * (usually) followed by message-specific data. The order of definitions in - * this file is as follows: - * - * (1) Structures used in several types of message. - * (2) Structures used in the initial handshaking. - * (3) Message types. - * (4) Encoding types. - * (5) For each message type, the form of the data following the type byte. - * Sometimes this is defined by a single structure but the more complex - * messages have to be explained by comments. - */ - - -/***************************************************************************** - * - * Structures used in several messages - * - *****************************************************************************/ - -/*----------------------------------------------------------------------------- - * Structure used to specify a rectangle. This structure is a multiple of 4 - * bytes so that it can be interspersed with 32-bit pixel data without - * affecting alignment. - */ - -typedef struct { - CARD16 x; - CARD16 y; - CARD16 w; - CARD16 h; -} rfbRectangle; - -#define sz_rfbRectangle 8 - - -/*----------------------------------------------------------------------------- - * Structure used to specify pixel format. - */ - -typedef struct { - - CARD8 bitsPerPixel; /* 8,16,32 only */ - - CARD8 depth; /* 8 to 32 */ - - CARD8 bigEndian; /* True if multi-byte pixels are interpreted - as big endian, or if single-bit-per-pixel - has most significant bit of the byte - corresponding to first (leftmost) pixel. Of - course this is meaningless for 8 bits/pix */ - - CARD8 trueColour; /* If false then we need a "colour map" to - convert pixels to RGB. If true, xxxMax and - xxxShift specify bits used for red, green - and blue */ - - /* the following fields are only meaningful if trueColour is true */ - - CARD16 redMax; /* maximum red value (= 2^n - 1 where n is the - number of bits used for red). Note this - value is always in big endian order. */ - - CARD16 greenMax; /* similar for green */ - - CARD16 blueMax; /* and blue */ - - CARD8 redShift; /* number of shifts needed to get the red - value in a pixel to the least significant - bit. To find the red value from a given - pixel, do the following: - 1) Swap pixel value according to bigEndian - (e.g. if bigEndian is false and host byte - order is big endian, then swap). - 2) Shift right by redShift. - 3) AND with redMax (in host byte order). - 4) You now have the red value between 0 and - redMax. */ - - CARD8 greenShift; /* similar for green */ - - CARD8 blueShift; /* and blue */ - - CARD8 pad1; - CARD16 pad2; - -} rfbPixelFormat; - -#define sz_rfbPixelFormat 16 - - - -/***************************************************************************** - * - * Initial handshaking messages - * - *****************************************************************************/ - -/*----------------------------------------------------------------------------- - * Protocol Version - * - * The server always sends 12 bytes to start which identifies the latest RFB - * protocol version number which it supports. These bytes are interpreted - * as a string of 12 ASCII characters in the format "RFB xxx.yyy\n" where - * xxx and yyy are the major and minor version numbers (for version 3.3 - * this is "RFB 003.003\n"). - * - * The client then replies with a similar 12-byte message giving the version - * number of the protocol which should actually be used (which may be different - * to that quoted by the server). - * - * It is intended that both clients and servers may provide some level of - * backwards compatibility by this mechanism. Servers in particular should - * attempt to provide backwards compatibility, and even forwards compatibility - * to some extent. For example if a client demands version 3.1 of the - * protocol, a 3.0 server can probably assume that by ignoring requests for - * encoding types it doesn't understand, everything will still work OK. This - * will probably not be the case for changes in the major version number. - * - * The format string below can be used in sprintf or sscanf to generate or - * decode the version string respectively. - */ - -#define rfbProtocolVersionFormat "RFB %03d.%03d\n" -#define rfbProtocolMajorVersion 3 -#define rfbProtocolMinorVersion 3 - -typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */ - -#define sz_rfbProtocolVersionMsg 12 - - -/*----------------------------------------------------------------------------- - * Authentication - * - * Once the protocol version has been decided, the server then sends a 32-bit - * word indicating whether any authentication is needed on the connection. - * The value of this word determines the authentication scheme in use. For - * version 3.0 of the protocol this may have one of the following values: - */ - -#define rfbConnFailed 0 -#define rfbNoAuth 1 -#define rfbVncAuth 2 - -/* - * rfbConnFailed: For some reason the connection failed (e.g. the server - * cannot support the desired protocol version). This is - * followed by a string describing the reason (where a - * string is specified as a 32-bit length followed by that - * many ASCII characters). - * - * rfbNoAuth: No authentication is needed. - * - * rfbVncAuth: The VNC authentication scheme is to be used. A 16-byte - * challenge follows, which the client encrypts as - * appropriate using the password and sends the resulting - * 16-byte response. If the response is correct, the - * server sends the 32-bit word rfbVncAuthOK. If a simple - * failure happens, the server sends rfbVncAuthFailed and - * closes the connection. If the server decides that too - * many failures have occurred, it sends rfbVncAuthTooMany - * and closes the connection. In the latter case, the - * server should not allow an immediate reconnection by - * the client. - */ - -#define rfbVncAuthOK 0 -#define rfbVncAuthFailed 1 -#define rfbVncAuthTooMany 2 - - -/*----------------------------------------------------------------------------- - * Client Initialisation Message - * - * Once the client and server are sure that they're happy to talk to one - * another, the client sends an initialisation message. At present this - * message only consists of a boolean indicating whether the server should try - * to share the desktop by leaving other clients connected, or give exclusive - * access to this client by disconnecting all other clients. - */ - -typedef struct { - CARD8 shared; -} rfbClientInitMsg; - -#define sz_rfbClientInitMsg 1 - - -/*----------------------------------------------------------------------------- - * Server Initialisation Message - * - * After the client initialisation message, the server sends one of its own. - * This tells the client the width and height of the server's framebuffer, - * its pixel format and the name associated with the desktop. - */ - -typedef struct { - CARD16 framebufferWidth; - CARD16 framebufferHeight; - rfbPixelFormat format; /* the server's preferred pixel format */ - CARD32 nameLength; - /* followed by char name[nameLength] */ -} rfbServerInitMsg; - -#define sz_rfbServerInitMsg (8 + sz_rfbPixelFormat) - - -/* - * Following the server initialisation message it's up to the client to send - * whichever protocol messages it wants. Typically it will send a - * SetPixelFormat message and a SetEncodings message, followed by a - * FramebufferUpdateRequest. From then on the server will send - * FramebufferUpdate messages in response to the client's - * FramebufferUpdateRequest messages. The client should send - * FramebufferUpdateRequest messages with incremental set to true when it has - * finished processing one FramebufferUpdate and is ready to process another. - * With a fast client, the rate at which FramebufferUpdateRequests are sent - * should be regulated to avoid hogging the network. - */ - - - -/***************************************************************************** - * - * Message types - * - *****************************************************************************/ - -/* server -> client */ - -#define rfbFramebufferUpdate 0 -#define rfbSetColourMapEntries 1 -#define rfbBell 2 -#define rfbServerCutText 3 - - -/* client -> server */ - -#define rfbSetPixelFormat 0 -#define rfbFixColourMapEntries 1 /* not currently supported */ -#define rfbSetEncodings 2 -#define rfbFramebufferUpdateRequest 3 -#define rfbKeyEvent 4 -#define rfbPointerEvent 5 -#define rfbClientCutText 6 - - - - -/***************************************************************************** - * - * Encoding types - * - *****************************************************************************/ - -#define rfbEncodingRaw 0 -#define rfbEncodingCopyRect 1 -#define rfbEncodingRRE 2 -#define rfbEncodingCoRRE 4 -#define rfbEncodingHextile 5 - - - -/***************************************************************************** - * - * Server -> client message definitions - * - *****************************************************************************/ - - -/*----------------------------------------------------------------------------- - * FramebufferUpdate - a block of rectangles to be copied to the framebuffer. - * - * This message consists of a header giving the number of rectangles of pixel - * data followed by the rectangles themselves. The header is padded so that - * together with the type byte it is an exact multiple of 4 bytes (to help - * with alignment of 32-bit pixels): - */ - -typedef struct { - CARD8 type; /* always rfbFramebufferUpdate */ - CARD8 pad; - CARD16 nRects; - /* followed by nRects rectangles */ -} rfbFramebufferUpdateMsg; - -#define sz_rfbFramebufferUpdateMsg 4 - -/* - * Each rectangle of pixel data consists of a header describing the position - * and size of the rectangle and a type word describing the encoding of the - * pixel data, followed finally by the pixel data. Note that if the client has - * not sent a SetEncodings message then it will only receive raw pixel data. - * Also note again that this structure is a multiple of 4 bytes. - */ - -typedef struct { - rfbRectangle r; - CARD32 encoding; /* one of the encoding types rfbEncoding... */ -} rfbFramebufferUpdateRectHeader; - -#define sz_rfbFramebufferUpdateRectHeader (sz_rfbRectangle + 4) - - -/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * Raw Encoding. Pixels are sent in top-to-bottom scanline order, - * left-to-right within a scanline with no padding in between. - */ - - -/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CopyRect Encoding. The pixels are specified simply by the x and y position - * of the source rectangle. - */ - -typedef struct { - CARD16 srcX; - CARD16 srcY; -} rfbCopyRect; - -#define sz_rfbCopyRect 4 - - -/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * RRE - Rise-and-Run-length Encoding. We have an rfbRREHeader structure - * giving the number of subrectangles following. Finally the data follows in - * the form [...] where each is - * []. - */ - -typedef struct { - CARD32 nSubrects; -} rfbRREHeader; - -#define sz_rfbRREHeader 4 - - -/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * CoRRE - Compact RRE Encoding. We have an rfbRREHeader structure giving - * the number of subrectangles following. Finally the data follows in the form - * [...] where each is - * []. This means that - * the whole rectangle must be at most 255x255 pixels. - */ - -typedef struct { - CARD8 x; - CARD8 y; - CARD8 w; - CARD8 h; -} rfbCoRRERectangle; - -#define sz_rfbCoRRERectangle 4 - - -/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * Hextile Encoding. The rectangle is divided up into "tiles" of 16x16 pixels, - * starting at the top left going in left-to-right, top-to-bottom order. If - * the width of the rectangle is not an exact multiple of 16 then the width of - * the last tile in each row will be correspondingly smaller. Similarly if the - * height is not an exact multiple of 16 then the height of each tile in the - * final row will also be smaller. Each tile begins with a "subencoding" type - * byte, which is a mask made up of a number of bits. If the Raw bit is set - * then the other bits are irrelevant; w*h pixel values follow (where w and h - * are the width and height of the tile). Otherwise the tile is encoded in a - * similar way to RRE, except that the position and size of each subrectangle - * can be specified in just two bytes. The other bits in the mask are as - * follows: - * - * BackgroundSpecified - if set, a pixel value follows which specifies - * the background colour for this tile. The first non-raw tile in a - * rectangle must have this bit set. If this bit isn't set then the - * background is the same as the last tile. - * - * ForegroundSpecified - if set, a pixel value follows which specifies - * the foreground colour to be used for all subrectangles in this tile. - * If this bit is set then the SubrectsColoured bit must be zero. - * - * AnySubrects - if set, a single byte follows giving the number of - * subrectangles following. If not set, there are no subrectangles (i.e. - * the whole tile is just solid background colour). - * - * SubrectsColoured - if set then each subrectangle is preceded by a pixel - * value giving the colour of that subrectangle. If not set, all - * subrectangles are the same colour, the foreground colour; if the - * ForegroundSpecified bit wasn't set then the foreground is the same as - * the last tile. - * - * The position and size of each subrectangle is specified in two bytes. The - * Pack macros below can be used to generate the two bytes from x, y, w, h, - * and the Extract macros can be used to extract the x, y, w, h values from - * the two bytes. - */ - -#define rfbHextileRaw (1 << 0) -#define rfbHextileBackgroundSpecified (1 << 1) -#define rfbHextileForegroundSpecified (1 << 2) -#define rfbHextileAnySubrects (1 << 3) -#define rfbHextileSubrectsColoured (1 << 4) - -#define rfbHextilePackXY(x,y) (((x) << 4) | (y)) -#define rfbHextilePackWH(w,h) ((((w)-1) << 4) | ((h)-1)) -#define rfbHextileExtractX(byte) ((byte) >> 4) -#define rfbHextileExtractY(byte) ((byte) & 0xf) -#define rfbHextileExtractW(byte) (((byte) >> 4) + 1) -#define rfbHextileExtractH(byte) (((byte) & 0xf) + 1) - - -/*----------------------------------------------------------------------------- - * SetColourMapEntries - these messages are only sent if the pixel - * format uses a "colour map" (i.e. trueColour false) and the client has not - * fixed the entire colour map using FixColourMapEntries. In addition they - * will only start being sent after the client has sent its first - * FramebufferUpdateRequest. So if the client always tells the server to use - * trueColour then it never needs to process this type of message. - */ - -typedef struct { - CARD8 type; /* always rfbSetColourMapEntries */ - CARD8 pad; - CARD16 firstColour; - CARD16 nColours; - - /* Followed by nColours * 3 * CARD16 - r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ - -} rfbSetColourMapEntriesMsg; - -#define sz_rfbSetColourMapEntriesMsg 6 - - - -/*----------------------------------------------------------------------------- - * Bell - ring a bell on the client if it has one. - */ - -typedef struct { - CARD8 type; /* always rfbBell */ -} rfbBellMsg; - -#define sz_rfbBellMsg 1 - - - -/*----------------------------------------------------------------------------- - * ServerCutText - the server has new text in its cut buffer. - */ - -typedef struct { - CARD8 type; /* always rfbServerCutText */ - CARD8 pad1; - CARD16 pad2; - CARD32 length; - /* followed by char text[length] */ -} rfbServerCutTextMsg; - -#define sz_rfbServerCutTextMsg 8 - - -/*----------------------------------------------------------------------------- - * Union of all server->client messages. - */ - -typedef union { - CARD8 type; - rfbFramebufferUpdateMsg fu; - rfbSetColourMapEntriesMsg scme; - rfbBellMsg b; - rfbServerCutTextMsg sct; -} rfbServerToClientMsg; - - - -/***************************************************************************** - * - * Message definitions (client -> server) - * - *****************************************************************************/ - - -/*----------------------------------------------------------------------------- - * SetPixelFormat - tell the RFB server the format in which the client wants - * pixels sent. - */ - -typedef struct { - CARD8 type; /* always rfbSetPixelFormat */ - CARD8 pad1; - CARD16 pad2; - rfbPixelFormat format; -} rfbSetPixelFormatMsg; - -#define sz_rfbSetPixelFormatMsg (sz_rfbPixelFormat + 4) - - -/*----------------------------------------------------------------------------- - * FixColourMapEntries - when the pixel format uses a "colour map", fix - * read-only colour map entries. - * - * ***************** NOT CURRENTLY SUPPORTED ***************** - */ - -typedef struct { - CARD8 type; /* always rfbFixColourMapEntries */ - CARD8 pad; - CARD16 firstColour; - CARD16 nColours; - - /* Followed by nColours * 3 * CARD16 - r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ - -} rfbFixColourMapEntriesMsg; - -#define sz_rfbFixColourMapEntriesMsg 6 - - -/*----------------------------------------------------------------------------- - * SetEncodings - tell the RFB server which encoding types we accept. Put them - * in order of preference, if we have any. We may always receive raw - * encoding, even if we don't specify it here. - */ - -typedef struct { - CARD8 type; /* always rfbSetEncodings */ - CARD8 pad; - CARD16 nEncodings; - /* followed by nEncodings * CARD32 encoding types */ -} rfbSetEncodingsMsg; - -#define sz_rfbSetEncodingsMsg 4 - - -/*----------------------------------------------------------------------------- - * FramebufferUpdateRequest - request for a framebuffer update. If incremental - * is true then the client just wants the changes since the last update. If - * false then it wants the whole of the specified rectangle. - */ - -typedef struct { - CARD8 type; /* always rfbFramebufferUpdateRequest */ - CARD8 incremental; - CARD16 x; - CARD16 y; - CARD16 w; - CARD16 h; -} rfbFramebufferUpdateRequestMsg; - -#define sz_rfbFramebufferUpdateRequestMsg 10 - - -/*----------------------------------------------------------------------------- - * KeyEvent - key press or release - * - * Keys are specified using the "keysym" values defined by the X Window System. - * For most ordinary keys, the keysym is the same as the corresponding ASCII - * value. Other common keys are: - * - * BackSpace 0xff08 - * Tab 0xff09 - * Return or Enter 0xff0d - * Escape 0xff1b - * Insert 0xff63 - * Delete 0xffff - * Home 0xff50 - * End 0xff57 - * Page Up 0xff55 - * Page Down 0xff56 - * Left 0xff51 - * Up 0xff52 - * Right 0xff53 - * Down 0xff54 - * F1 0xffbe - * F2 0xffbf - * ... ... - * F12 0xffc9 - * Shift 0xffe1 - * Control 0xffe3 - * Meta 0xffe7 - * Alt 0xffe9 - */ - -typedef struct { - CARD8 type; /* always rfbKeyEvent */ - CARD8 down; /* true if down (press), false if up */ - CARD16 pad; - CARD32 key; /* key is specified as an X keysym */ -} rfbKeyEventMsg; - -#define sz_rfbKeyEventMsg 8 - - -/*----------------------------------------------------------------------------- - * PointerEvent - mouse/pen move and/or button press. - */ - -typedef struct { - CARD8 type; /* always rfbPointerEvent */ - CARD8 buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */ - CARD16 x; - CARD16 y; -} rfbPointerEventMsg; - -#define rfbButton1Mask 1 -#define rfbButton2Mask 2 -#define rfbButton3Mask 4 - -#define sz_rfbPointerEventMsg 6 - - - -/*----------------------------------------------------------------------------- - * ClientCutText - the client has new text in its cut buffer. - */ - -typedef struct { - CARD8 type; /* always rfbClientCutText */ - CARD8 pad1; - CARD16 pad2; - CARD32 length; - /* followed by char text[length] */ -} rfbClientCutTextMsg; - -#define sz_rfbClientCutTextMsg 8 - - - -/*----------------------------------------------------------------------------- - * Union of all client->server messages. - */ - -typedef union { - CARD8 type; - rfbSetPixelFormatMsg spf; - rfbFixColourMapEntriesMsg fcme; - rfbSetEncodingsMsg se; - rfbFramebufferUpdateRequestMsg fur; - rfbKeyEventMsg ke; - rfbPointerEventMsg pe; - rfbClientCutTextMsg cct; -} rfbClientToServerMsg; diff --git a/tools/ioemu/gui/sdl.h b/tools/ioemu/gui/sdl.h deleted file mode 100644 index c8df029f05..0000000000 --- a/tools/ioemu/gui/sdl.h +++ /dev/null @@ -1,1038 +0,0 @@ -#define BX_HEADERBAR_FG_RED 0x10 -#define BX_HEADERBAR_FG_GREEN 0x10 -#define BX_HEADERBAR_FG_BLUE 0x10 -#define BX_HEADERBAR_BG_RED 0xD0 -#define BX_HEADERBAR_BG_GREEN 0xD0 -#define BX_HEADERBAR_BG_BLUE 0xD0 - -unsigned char sdl_font8x16[256][16] = { - { 0, 0, 0, 0, 0, 0, 0, 0, // 0 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 126, 129, 165, 129, 129, 189, // 1 - 153, 129, 129, 126, 0, 0, 0, 0 }, - { 0, 0, 126, 255, 219, 255, 255, 195, // 2 - 231, 255, 255, 126, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 108, 254, 254, 254, // 3 - 254, 124, 56, 16, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 16, 56, 124, 254, // 4 - 124, 56, 16, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 24, 60, 60, 231, 231, // 5 - 231, 24, 24, 60, 0, 0, 0, 0 }, - { 0, 0, 0, 24, 60, 126, 255, 255, // 6 - 126, 24, 24, 60, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 24, 60, // 7 - 60, 24, 0, 0, 0, 0, 0, 0 }, - { 255, 255, 255, 255, 255, 255, 231, 195, // 8 - 195, 231, 255, 255, 255, 255, 255, 255 }, - { 0, 0, 0, 0, 0, 60, 102, 66, // 9 - 66, 102, 60, 0, 0, 0, 0, 0 }, - { 255, 255, 255, 255, 255, 195, 153, 189, // 10 - 189, 153, 195, 255, 255, 255, 255, 255 }, - { 0, 0, 30, 14, 26, 50, 120, 204, // 11 - 204, 204, 204, 120, 0, 0, 0, 0 }, - { 0, 0, 60, 102, 102, 102, 102, 60, // 12 - 24, 126, 24, 24, 0, 0, 0, 0 }, - { 0, 0, 63, 51, 63, 48, 48, 48, // 13 - 48, 112, 240, 224, 0, 0, 0, 0 }, - { 0, 0, 127, 99, 127, 99, 99, 99, // 14 - 99, 103, 231, 230, 192, 0, 0, 0 }, - { 0, 0, 0, 24, 24, 219, 60, 231, // 15 - 60, 219, 24, 24, 0, 0, 0, 0 }, - { 0, 128, 192, 224, 240, 248, 254, 248, // 16 - 240, 224, 192, 128, 0, 0, 0, 0 }, - { 0, 2, 6, 14, 30, 62, 254, 62, // 17 - 30, 14, 6, 2, 0, 0, 0, 0 }, - { 0, 0, 24, 60, 126, 24, 24, 24, // 18 - 126, 60, 24, 0, 0, 0, 0, 0 }, - { 0, 0, 102, 102, 102, 102, 102, 102, // 19 - 102, 0, 102, 102, 0, 0, 0, 0 }, - { 0, 0, 127, 219, 219, 219, 123, 27, // 20 - 27, 27, 27, 27, 0, 0, 0, 0 }, - { 0, 124, 198, 96, 56, 108, 198, 198, // 21 - 108, 56, 12, 198, 124, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, // 22 - 254, 254, 254, 254, 0, 0, 0, 0 }, - { 0, 0, 24, 60, 126, 24, 24, 24, // 23 - 126, 60, 24, 126, 0, 0, 0, 0 }, - { 0, 0, 24, 60, 126, 24, 24, 24, // 24 - 24, 24, 24, 24, 0, 0, 0, 0 }, - { 0, 0, 24, 24, 24, 24, 24, 24, // 25 - 24, 126, 60, 24, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 24, 12, 254, // 26 - 12, 24, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 48, 96, 254, // 27 - 96, 48, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 192, 192, // 28 - 192, 254, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 40, 108, 254, // 29 - 108, 40, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 16, 56, 56, 124, // 30 - 124, 254, 254, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 254, 254, 124, 124, // 31 - 56, 56, 16, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, // 32 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 24, 60, 60, 60, 24, 24, // 33 - 24, 0, 24, 24, 0, 0, 0, 0 }, - { 0, 102, 102, 102, 36, 0, 0, 0, // 34 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 108, 108, 254, 108, 108, // 35 - 108, 254, 108, 108, 0, 0, 0, 0 }, - { 24, 24, 124, 198, 194, 192, 124, 6, // 36 - 6, 134, 198, 124, 24, 24, 0, 0 }, - { 0, 0, 0, 0, 194, 198, 12, 24, // 37 - 48, 96, 198, 134, 0, 0, 0, 0 }, - { 0, 0, 56, 108, 108, 56, 118, 220, // 38 - 204, 204, 204, 118, 0, 0, 0, 0 }, - { 0, 48, 48, 48, 96, 0, 0, 0, // 39 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 12, 24, 48, 48, 48, 48, // 40 - 48, 48, 24, 12, 0, 0, 0, 0 }, - { 0, 0, 48, 24, 12, 12, 12, 12, // 41 - 12, 12, 24, 48, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 102, 60, 255, // 42 - 60, 102, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 24, 24, 126, // 43 - 24, 24, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, // 44 - 0, 24, 24, 24, 48, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 254, // 45 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, // 46 - 0, 0, 24, 24, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 2, 6, 12, 24, // 47 - 48, 96, 192, 128, 0, 0, 0, 0 }, - { 0, 0, 56, 108, 198, 198, 214, 214, // 48 - 198, 198, 108, 56, 0, 0, 0, 0 }, - { 0, 0, 24, 56, 120, 24, 24, 24, // 49 - 24, 24, 24, 126, 0, 0, 0, 0 }, - { 0, 0, 124, 198, 6, 12, 24, 48, // 50 - 96, 192, 198, 254, 0, 0, 0, 0 }, - { 0, 0, 124, 198, 6, 6, 60, 6, // 51 - 6, 6, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 12, 28, 60, 108, 204, 254, // 52 - 12, 12, 12, 30, 0, 0, 0, 0 }, - { 0, 0, 254, 192, 192, 192, 252, 6, // 53 - 6, 6, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 56, 96, 192, 192, 252, 198, // 54 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 254, 198, 6, 6, 12, 24, // 55 - 48, 48, 48, 48, 0, 0, 0, 0 }, - { 0, 0, 124, 198, 198, 198, 124, 198, // 56 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 124, 198, 198, 198, 126, 6, // 57 - 6, 6, 12, 120, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 24, 24, 0, 0, // 58 - 0, 24, 24, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 24, 24, 0, 0, // 59 - 0, 24, 24, 48, 0, 0, 0, 0 }, - { 0, 0, 0, 6, 12, 24, 48, 96, // 60 - 48, 24, 12, 6, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 126, 0, 0, // 61 - 126, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 96, 48, 24, 12, 6, // 62 - 12, 24, 48, 96, 0, 0, 0, 0 }, - { 0, 0, 124, 198, 198, 12, 24, 24, // 63 - 24, 0, 24, 24, 0, 0, 0, 0 }, - { 0, 0, 0, 124, 198, 198, 222, 222, // 64 - 222, 220, 192, 124, 0, 0, 0, 0 }, - { 0, 0, 16, 56, 108, 198, 198, 254, // 65 - 198, 198, 198, 198, 0, 0, 0, 0 }, - { 0, 0, 252, 102, 102, 102, 124, 102, // 66 - 102, 102, 102, 252, 0, 0, 0, 0 }, - { 0, 0, 60, 102, 194, 192, 192, 192, // 67 - 192, 194, 102, 60, 0, 0, 0, 0 }, - { 0, 0, 248, 108, 102, 102, 102, 102, // 68 - 102, 102, 108, 248, 0, 0, 0, 0 }, - { 0, 0, 254, 102, 98, 104, 120, 104, // 69 - 96, 98, 102, 254, 0, 0, 0, 0 }, - { 0, 0, 254, 102, 98, 104, 120, 104, // 70 - 96, 96, 96, 240, 0, 0, 0, 0 }, - { 0, 0, 60, 102, 194, 192, 192, 222, // 71 - 198, 198, 102, 58, 0, 0, 0, 0 }, - { 0, 0, 198, 198, 198, 198, 254, 198, // 72 - 198, 198, 198, 198, 0, 0, 0, 0 }, - { 0, 0, 60, 24, 24, 24, 24, 24, // 73 - 24, 24, 24, 60, 0, 0, 0, 0 }, - { 0, 0, 30, 12, 12, 12, 12, 12, // 74 - 204, 204, 204, 120, 0, 0, 0, 0 }, - { 0, 0, 230, 102, 102, 108, 120, 120, // 75 - 108, 102, 102, 230, 0, 0, 0, 0 }, - { 0, 0, 240, 96, 96, 96, 96, 96, // 76 - 96, 98, 102, 254, 0, 0, 0, 0 }, - { 0, 0, 198, 238, 254, 254, 214, 198, // 77 - 198, 198, 198, 198, 0, 0, 0, 0 }, - { 0, 0, 198, 230, 246, 254, 222, 206, // 78 - 198, 198, 198, 198, 0, 0, 0, 0 }, - { 0, 0, 124, 198, 198, 198, 198, 198, // 79 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 252, 102, 102, 102, 124, 96, // 80 - 96, 96, 96, 240, 0, 0, 0, 0 }, - { 0, 0, 124, 198, 198, 198, 198, 198, // 81 - 198, 214, 222, 124, 12, 14, 0, 0 }, - { 0, 0, 252, 102, 102, 102, 124, 108, // 82 - 102, 102, 102, 230, 0, 0, 0, 0 }, - { 0, 0, 124, 198, 198, 96, 56, 12, // 83 - 6, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 126, 126, 90, 24, 24, 24, // 84 - 24, 24, 24, 60, 0, 0, 0, 0 }, - { 0, 0, 198, 198, 198, 198, 198, 198, // 85 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 198, 198, 198, 198, 198, 198, // 86 - 198, 108, 56, 16, 0, 0, 0, 0 }, - { 0, 0, 198, 198, 198, 198, 214, 214, // 87 - 214, 254, 238, 108, 0, 0, 0, 0 }, - { 0, 0, 198, 198, 108, 124, 56, 56, // 88 - 124, 108, 198, 198, 0, 0, 0, 0 }, - { 0, 0, 102, 102, 102, 102, 60, 24, // 89 - 24, 24, 24, 60, 0, 0, 0, 0 }, - { 0, 0, 254, 198, 134, 12, 24, 48, // 90 - 96, 194, 198, 254, 0, 0, 0, 0 }, - { 0, 0, 60, 48, 48, 48, 48, 48, // 91 - 48, 48, 48, 60, 0, 0, 0, 0 }, - { 0, 0, 0, 128, 192, 224, 112, 56, // 92 - 28, 14, 6, 2, 0, 0, 0, 0 }, - { 0, 0, 60, 12, 12, 12, 12, 12, // 93 - 12, 12, 12, 60, 0, 0, 0, 0 }, - { 16, 56, 108, 198, 0, 0, 0, 0, // 94 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, // 95 - 0, 0, 0, 0, 0, 255, 0, 0 }, - { 0, 48, 24, 12, 0, 0, 0, 0, // 96 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 120, 12, 124, // 97 - 204, 204, 204, 118, 0, 0, 0, 0 }, - { 0, 0, 224, 96, 96, 120, 108, 102, // 98 - 102, 102, 102, 124, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 124, 198, 192, // 99 - 192, 192, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 28, 12, 12, 60, 108, 204, // 100 - 204, 204, 204, 118, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 124, 198, 254, // 101 - 192, 192, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 28, 54, 50, 48, 120, 48, // 102 - 48, 48, 48, 120, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 118, 204, 204, // 103 - 204, 204, 204, 124, 12, 204, 120, 0 }, - { 0, 0, 224, 96, 96, 108, 118, 102, // 104 - 102, 102, 102, 230, 0, 0, 0, 0 }, - { 0, 0, 24, 24, 0, 56, 24, 24, // 105 - 24, 24, 24, 60, 0, 0, 0, 0 }, - { 0, 0, 6, 6, 0, 14, 6, 6, // 106 - 6, 6, 6, 6, 102, 102, 60, 0 }, - { 0, 0, 224, 96, 96, 102, 108, 120, // 107 - 120, 108, 102, 230, 0, 0, 0, 0 }, - { 0, 0, 56, 24, 24, 24, 24, 24, // 108 - 24, 24, 24, 60, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 236, 254, 214, // 109 - 214, 214, 214, 198, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 220, 102, 102, // 110 - 102, 102, 102, 102, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 124, 198, 198, // 111 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 220, 102, 102, // 112 - 102, 102, 102, 124, 96, 96, 240, 0 }, - { 0, 0, 0, 0, 0, 118, 204, 204, // 113 - 204, 204, 204, 124, 12, 12, 30, 0 }, - { 0, 0, 0, 0, 0, 220, 118, 102, // 114 - 96, 96, 96, 240, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 124, 198, 96, // 115 - 56, 12, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 16, 48, 48, 252, 48, 48, // 116 - 48, 48, 54, 28, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 204, 204, 204, // 117 - 204, 204, 204, 118, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 198, 198, 198, // 118 - 198, 198, 108, 56, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 198, 198, 214, // 119 - 214, 214, 254, 108, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 198, 108, 56, // 120 - 56, 56, 108, 198, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 198, 198, 198, // 121 - 198, 198, 198, 126, 6, 12, 248, 0 }, - { 0, 0, 0, 0, 0, 254, 204, 24, // 122 - 48, 96, 198, 254, 0, 0, 0, 0 }, - { 0, 0, 14, 24, 24, 24, 112, 24, // 123 - 24, 24, 24, 14, 0, 0, 0, 0 }, - { 0, 0, 24, 24, 24, 24, 24, 24, // 124 - 24, 24, 24, 24, 0, 0, 0, 0 }, - { 0, 0, 112, 24, 24, 24, 14, 24, // 125 - 24, 24, 24, 112, 0, 0, 0, 0 }, - { 0, 118, 220, 0, 0, 0, 0, 0, // 126 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 16, 56, 108, 198, // 127 - 198, 198, 254, 0, 0, 0, 0, 0 }, - { 0, 0, 60, 102, 194, 192, 192, 192, // 128 - 192, 194, 102, 60, 24, 112, 0, 0 }, - { 0, 0, 204, 0, 0, 204, 204, 204, // 129 - 204, 204, 204, 118, 0, 0, 0, 0 }, - { 0, 12, 24, 48, 0, 124, 198, 254, // 130 - 192, 192, 198, 124, 0, 0, 0, 0 }, - { 0, 16, 56, 108, 0, 120, 12, 124, // 131 - 204, 204, 204, 118, 0, 0, 0, 0 }, - { 0, 0, 204, 0, 0, 120, 12, 124, // 132 - 204, 204, 204, 118, 0, 0, 0, 0 }, - { 0, 96, 48, 24, 0, 120, 12, 124, // 133 - 204, 204, 204, 118, 0, 0, 0, 0 }, - { 0, 56, 108, 56, 0, 120, 12, 124, // 134 - 204, 204, 204, 118, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 124, 198, 192, // 135 - 192, 192, 198, 124, 24, 112, 0, 0 }, - { 0, 16, 56, 108, 0, 124, 198, 254, // 136 - 192, 192, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 198, 0, 0, 124, 198, 254, // 137 - 192, 192, 198, 124, 0, 0, 0, 0 }, - { 0, 96, 48, 24, 0, 124, 198, 254, // 138 - 192, 192, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 102, 0, 0, 56, 24, 24, // 139 - 24, 24, 24, 60, 0, 0, 0, 0 }, - { 0, 24, 60, 102, 0, 56, 24, 24, // 140 - 24, 24, 24, 60, 0, 0, 0, 0 }, - { 0, 96, 48, 24, 0, 56, 24, 24, // 141 - 24, 24, 24, 60, 0, 0, 0, 0 }, - { 0, 198, 0, 16, 56, 108, 198, 198, // 142 - 254, 198, 198, 198, 0, 0, 0, 0 }, - { 56, 108, 56, 16, 56, 108, 198, 198, // 143 - 254, 198, 198, 198, 0, 0, 0, 0 }, - { 12, 24, 0, 254, 102, 98, 104, 120, // 144 - 104, 98, 102, 254, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 236, 54, 54, // 145 - 126, 216, 216, 110, 0, 0, 0, 0 }, - { 0, 0, 62, 108, 204, 204, 254, 204, // 146 - 204, 204, 204, 206, 0, 0, 0, 0 }, - { 0, 16, 56, 108, 0, 124, 198, 198, // 147 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 198, 0, 0, 124, 198, 198, // 148 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 96, 48, 24, 0, 124, 198, 198, // 149 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 48, 120, 204, 0, 204, 204, 204, // 150 - 204, 204, 204, 118, 0, 0, 0, 0 }, - { 0, 96, 48, 24, 0, 204, 204, 204, // 151 - 204, 204, 204, 118, 0, 0, 0, 0 }, - { 0, 0, 198, 0, 0, 198, 198, 198, // 152 - 198, 198, 198, 126, 6, 12, 120, 0 }, - { 0, 198, 0, 124, 198, 198, 198, 198, // 153 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 198, 0, 198, 198, 198, 198, 198, // 154 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 124, 206, 222, // 155 - 246, 230, 198, 124, 0, 0, 0, 0 }, - { 0, 56, 108, 100, 96, 240, 96, 96, // 156 - 96, 96, 230, 252, 0, 0, 0, 0 }, - { 0, 4, 124, 206, 206, 214, 214, 214, // 157 - 214, 230, 230, 124, 64, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 198, 108, 56, // 158 - 56, 108, 198, 0, 0, 0, 0, 0 }, - { 0, 14, 27, 24, 24, 24, 126, 24, // 159 - 24, 24, 216, 112, 0, 0, 0, 0 }, - { 0, 24, 48, 96, 0, 120, 12, 124, // 160 - 204, 204, 204, 118, 0, 0, 0, 0 }, - { 0, 12, 24, 48, 0, 56, 24, 24, // 161 - 24, 24, 24, 60, 0, 0, 0, 0 }, - { 0, 24, 48, 96, 0, 124, 198, 198, // 162 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 24, 48, 96, 0, 204, 204, 204, // 163 - 204, 204, 204, 118, 0, 0, 0, 0 }, - { 0, 0, 118, 220, 0, 220, 102, 102, // 164 - 102, 102, 102, 102, 0, 0, 0, 0 }, - { 118, 220, 0, 198, 230, 246, 254, 222, // 165 - 206, 198, 198, 198, 0, 0, 0, 0 }, - { 0, 0, 60, 108, 108, 62, 0, 126, // 166 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 56, 108, 108, 56, 0, 124, // 167 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 48, 48, 0, 48, 48, 96, // 168 - 192, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 124, 130, 178, 170, 178, 170, // 169 - 170, 130, 124, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 254, 6, // 170 - 6, 6, 6, 0, 0, 0, 0, 0 }, - { 0, 96, 224, 98, 102, 108, 24, 48, // 171 - 96, 220, 134, 12, 24, 62, 0, 0 }, - { 0, 96, 224, 98, 102, 108, 24, 48, // 172 - 102, 206, 154, 63, 6, 6, 0, 0 }, - { 0, 0, 24, 24, 0, 24, 24, 24, // 173 - 60, 60, 60, 24, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 54, 108, 216, // 174 - 108, 54, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 216, 108, 54, // 175 - 108, 216, 0, 0, 0, 0, 0, 0 }, - { 17, 68, 17, 68, 17, 68, 17, 68, // 176 - 17, 68, 17, 68, 17, 68, 17, 68 }, - { 85, 170, 85, 170, 85, 170, 85, 170, // 177 - 85, 170, 85, 170, 85, 170, 85, 170 }, - { 221, 119, 221, 119, 221, 119, 221, 119, // 178 - 221, 119, 221, 119, 221, 119, 221, 119 }, - { 24, 24, 24, 24, 24, 24, 24, 24, // 179 - 24, 24, 24, 24, 24, 24, 24, 24 }, - { 24, 24, 24, 24, 24, 24, 24, 248, // 180 - 24, 24, 24, 24, 24, 24, 24, 24 }, - { 96, 192, 16, 56, 108, 198, 198, 254, // 181 - 198, 198, 198, 198, 0, 0, 0, 0 }, - { 124, 198, 16, 56, 108, 198, 198, 254, // 182 - 198, 198, 198, 198, 0, 0, 0, 0 }, - { 12, 6, 16, 56, 108, 198, 198, 254, // 183 - 198, 198, 198, 198, 0, 0, 0, 0 }, - { 0, 0, 124, 130, 154, 162, 162, 162, // 184 - 154, 130, 124, 0, 0, 0, 0, 0 }, - { 54, 54, 54, 54, 54, 246, 6, 246, // 185 - 54, 54, 54, 54, 54, 54, 54, 54 }, - { 54, 54, 54, 54, 54, 54, 54, 54, // 186 - 54, 54, 54, 54, 54, 54, 54, 54 }, - { 0, 0, 0, 0, 0, 254, 6, 246, // 187 - 54, 54, 54, 54, 54, 54, 54, 54 }, - { 54, 54, 54, 54, 54, 246, 6, 254, // 188 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 24, 24, 124, 198, 192, 192, // 189 - 198, 124, 24, 24, 0, 0, 0, 0 }, - { 0, 0, 0, 102, 102, 60, 24, 126, // 190 - 24, 126, 24, 24, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 248, // 191 - 24, 24, 24, 24, 24, 24, 24, 24 }, - { 24, 24, 24, 24, 24, 24, 24, 31, // 192 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 24, 24, 24, 24, 24, 24, 24, 255, // 193 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 255, // 194 - 24, 24, 24, 24, 24, 24, 24, 24 }, - { 24, 24, 24, 24, 24, 24, 24, 31, // 195 - 24, 24, 24, 24, 24, 24, 24, 24 }, - { 0, 0, 0, 0, 0, 0, 0, 255, // 196 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 24, 24, 24, 24, 24, 24, 24, 255, // 197 - 24, 24, 24, 24, 24, 24, 24, 24 }, - { 0, 0, 118, 220, 0, 120, 12, 124, // 198 - 204, 204, 204, 118, 0, 0, 0, 0 }, - { 118, 220, 0, 56, 108, 198, 198, 254, // 199 - 198, 198, 198, 198, 0, 0, 0, 0 }, - { 54, 54, 54, 54, 54, 55, 48, 63, // 200 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 63, 48, 55, // 201 - 54, 54, 54, 54, 54, 54, 54, 54 }, - { 54, 54, 54, 54, 54, 247, 0, 255, // 202 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 255, 0, 247, // 203 - 54, 54, 54, 54, 54, 54, 54, 54 }, - { 54, 54, 54, 54, 54, 55, 48, 55, // 204 - 54, 54, 54, 54, 54, 54, 54, 54 }, - { 0, 0, 0, 0, 0, 255, 0, 255, // 205 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 54, 54, 54, 54, 54, 247, 0, 247, // 206 - 54, 54, 54, 54, 54, 54, 54, 54 }, - { 0, 0, 0, 0, 198, 124, 198, 198, // 207 - 198, 198, 124, 198, 0, 0, 0, 0 }, - { 0, 0, 52, 24, 44, 6, 62, 102, // 208 - 102, 102, 102, 60, 0, 0, 0, 0 }, - { 0, 0, 248, 108, 102, 102, 246, 102, // 209 - 102, 102, 108, 248, 0, 0, 0, 0 }, - { 56, 108, 0, 254, 102, 98, 104, 120, // 210 - 104, 98, 102, 254, 0, 0, 0, 0 }, - { 0, 198, 0, 254, 102, 98, 104, 120, // 211 - 104, 98, 102, 254, 0, 0, 0, 0 }, - { 48, 24, 0, 254, 102, 98, 104, 120, // 212 - 104, 98, 102, 254, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 56, 24, 24, // 213 - 24, 24, 24, 60, 0, 0, 0, 0 }, - { 12, 24, 0, 60, 24, 24, 24, 24, // 214 - 24, 24, 24, 60, 0, 0, 0, 0 }, - { 60, 102, 0, 60, 24, 24, 24, 24, // 215 - 24, 24, 24, 60, 0, 0, 0, 0 }, - { 0, 102, 0, 60, 24, 24, 24, 24, // 216 - 24, 24, 24, 60, 0, 0, 0, 0 }, - { 24, 24, 24, 24, 24, 24, 24, 248, // 217 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 31, // 218 - 24, 24, 24, 24, 24, 24, 24, 24 }, - { 255, 255, 255, 255, 255, 255, 255, 255, // 219 - 255, 255, 255, 255, 255, 255, 255, 255 }, - { 0, 0, 0, 0, 0, 0, 0, 255, // 220 - 255, 255, 255, 255, 255, 255, 255, 255 }, - { 0, 24, 24, 24, 24, 24, 0, 0, // 221 - 24, 24, 24, 24, 24, 0, 0, 0 }, - { 48, 24, 0, 60, 24, 24, 24, 24, // 222 - 24, 24, 24, 60, 0, 0, 0, 0 }, - { 255, 255, 255, 255, 255, 255, 255, 0, // 223 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 24, 48, 0, 124, 198, 198, 198, 198, // 224 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 120, 204, 204, 204, 216, 204, // 225 - 198, 198, 198, 204, 0, 0, 0, 0 }, - { 56, 108, 0, 124, 198, 198, 198, 198, // 226 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 48, 24, 0, 124, 198, 198, 198, 198, // 227 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 118, 220, 0, 124, 198, 198, // 228 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 118, 220, 0, 124, 198, 198, 198, 198, // 229 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 102, 102, 102, // 230 - 102, 102, 102, 124, 96, 96, 192, 0 }, - { 0, 0, 224, 96, 96, 124, 102, 102, // 231 - 102, 102, 102, 124, 96, 96, 240, 0 }, - { 0, 0, 240, 96, 124, 102, 102, 102, // 232 - 102, 124, 96, 240, 0, 0, 0, 0 }, - { 24, 48, 0, 198, 198, 198, 198, 198, // 233 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 56, 108, 0, 198, 198, 198, 198, 198, // 234 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 48, 24, 0, 198, 198, 198, 198, 198, // 235 - 198, 198, 198, 124, 0, 0, 0, 0 }, - { 0, 12, 24, 48, 0, 198, 198, 198, // 236 - 198, 198, 198, 126, 6, 12, 248, 0 }, - { 12, 24, 0, 102, 102, 102, 102, 60, // 237 - 24, 24, 24, 60, 0, 0, 0, 0 }, - { 0, 255, 0, 0, 0, 0, 0, 0, // 238 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 12, 24, 48, 0, 0, 0, 0, // 239 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 254, // 240 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 24, 24, 126, 24, // 241 - 24, 0, 0, 126, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, // 242 - 0, 0, 0, 0, 255, 0, 255, 0 }, - { 0, 224, 48, 98, 54, 236, 24, 48, // 243 - 102, 206, 154, 63, 6, 6, 0, 0 }, - { 0, 0, 127, 219, 219, 219, 123, 27, // 244 - 27, 27, 27, 27, 0, 0, 0, 0 }, - { 0, 124, 198, 96, 56, 108, 198, 198, // 245 - 108, 56, 12, 198, 124, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 24, 0, 126, // 246 - 0, 24, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, // 247 - 0, 0, 0, 24, 12, 120, 0, 0 }, - { 0, 56, 108, 108, 56, 0, 0, 0, // 248 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 198, 0, 0, 0, 0, 0, 0, // 249 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 24, // 250 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 24, 56, 24, 24, 24, 60, 0, // 251 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 124, 6, 60, 6, 6, 124, 0, // 252 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 60, 102, 12, 24, 50, 126, 0, // 253 - 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 126, 126, 126, 126, // 254 - 126, 126, 126, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, // 255 - 0, 0, 0, 0, 0, 0, 0, 0 }}; - -unsigned char sdl_font8x8[256][8] = { - { 0, 0, 0, 0, 0, 0, 0, 0 }, // 0 - { 126, 129, 165, 129, 189, 153, 129, 126 }, // 1 - { 126, 255, 219, 255, 195, 231, 255, 126 }, // 2 - { 108, 254, 254, 254, 124, 56, 16, 0 }, // 3 - { 16, 56, 124, 254, 124, 56, 16, 0 }, // 4 - { 56, 124, 56, 254, 254, 214, 16, 56 }, // 5 - { 16, 56, 124, 254, 254, 124, 16, 56 }, // 6 - { 0, 0, 24, 60, 60, 24, 0, 0 }, // 7 - { 255, 255, 231, 195, 195, 231, 255, 255 }, // 8 - { 0, 60, 102, 66, 66, 102, 60, 0 }, // 9 - { 255, 195, 153, 189, 189, 153, 195, 255 }, // 10 - { 15, 7, 15, 125, 204, 204, 204, 120 }, // 11 - { 60, 102, 102, 102, 60, 24, 126, 24 }, // 12 - { 63, 51, 63, 48, 48, 112, 240, 224 }, // 13 - { 127, 99, 127, 99, 99, 103, 230, 192 }, // 14 - { 24, 219, 60, 231, 231, 60, 219, 24 }, // 15 - { 128, 224, 248, 254, 248, 224, 128, 0 }, // 16 - { 2, 14, 62, 254, 62, 14, 2, 0 }, // 17 - { 24, 60, 126, 24, 24, 126, 60, 24 }, // 18 - { 102, 102, 102, 102, 102, 0, 102, 0 }, // 19 - { 127, 219, 219, 123, 27, 27, 27, 0 }, // 20 - { 62, 97, 60, 102, 102, 60, 134, 124 }, // 21 - { 0, 0, 0, 0, 126, 126, 126, 0 }, // 22 - { 24, 60, 126, 24, 126, 60, 24, 255 }, // 23 - { 24, 60, 126, 24, 24, 24, 24, 0 }, // 24 - { 24, 24, 24, 24, 126, 60, 24, 0 }, // 25 - { 0, 24, 12, 254, 12, 24, 0, 0 }, // 26 - { 0, 48, 96, 254, 96, 48, 0, 0 }, // 27 - { 0, 0, 192, 192, 192, 254, 0, 0 }, // 28 - { 0, 36, 102, 255, 102, 36, 0, 0 }, // 29 - { 0, 24, 60, 126, 255, 255, 0, 0 }, // 30 - { 0, 255, 255, 126, 60, 24, 0, 0 }, // 31 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // 32 - { 24, 60, 60, 24, 24, 0, 24, 0 }, // 33 - { 102, 102, 36, 0, 0, 0, 0, 0 }, // 34 - { 108, 108, 254, 108, 254, 108, 108, 0 }, // 35 - { 24, 62, 96, 60, 6, 124, 24, 0 }, // 36 - { 0, 198, 204, 24, 48, 102, 198, 0 }, // 37 - { 56, 108, 56, 118, 220, 204, 118, 0 }, // 38 - { 24, 24, 48, 0, 0, 0, 0, 0 }, // 39 - { 12, 24, 48, 48, 48, 24, 12, 0 }, // 40 - { 48, 24, 12, 12, 12, 24, 48, 0 }, // 41 - { 0, 102, 60, 231, 60, 102, 0, 0 }, // 42 - { 0, 24, 24, 126, 24, 24, 0, 0 }, // 43 - { 0, 0, 0, 0, 0, 24, 24, 48 }, // 44 - { 0, 0, 0, 126, 0, 0, 0, 0 }, // 45 - { 0, 0, 0, 0, 0, 24, 24, 0 }, // 46 - { 6, 12, 24, 48, 96, 192, 128, 0 }, // 47 - { 124, 198, 206, 222, 246, 230, 124, 0 }, // 48 - { 24, 56, 24, 24, 24, 24, 126, 0 }, // 49 - { 124, 198, 6, 28, 48, 102, 254, 0 }, // 50 - { 124, 198, 6, 60, 6, 198, 124, 0 }, // 51 - { 28, 60, 108, 204, 254, 12, 30, 0 }, // 52 - { 254, 192, 192, 252, 6, 198, 124, 0 }, // 53 - { 56, 96, 192, 252, 198, 198, 124, 0 }, // 54 - { 254, 198, 12, 24, 48, 48, 48, 0 }, // 55 - { 124, 198, 198, 124, 198, 198, 124, 0 }, // 56 - { 124, 198, 198, 126, 6, 12, 120, 0 }, // 57 - { 0, 24, 24, 0, 0, 24, 24, 0 }, // 58 - { 0, 24, 24, 0, 0, 24, 24, 48 }, // 59 - { 6, 12, 24, 48, 24, 12, 6, 0 }, // 60 - { 0, 0, 126, 0, 0, 126, 0, 0 }, // 61 - { 96, 48, 24, 12, 24, 48, 96, 0 }, // 62 - { 124, 198, 12, 24, 24, 0, 24, 0 }, // 63 - { 124, 198, 222, 222, 222, 192, 120, 0 }, // 64 - { 56, 108, 198, 254, 198, 198, 198, 0 }, // 65 - { 252, 102, 102, 124, 102, 102, 252, 0 }, // 66 - { 60, 102, 192, 192, 192, 102, 60, 0 }, // 67 - { 248, 108, 102, 102, 102, 108, 248, 0 }, // 68 - { 254, 98, 104, 120, 104, 98, 254, 0 }, // 69 - { 254, 98, 104, 120, 104, 96, 240, 0 }, // 70 - { 60, 102, 192, 192, 206, 102, 58, 0 }, // 71 - { 198, 198, 198, 254, 198, 198, 198, 0 }, // 72 - { 60, 24, 24, 24, 24, 24, 60, 0 }, // 73 - { 30, 12, 12, 12, 204, 204, 120, 0 }, // 74 - { 230, 102, 108, 120, 108, 102, 230, 0 }, // 75 - { 240, 96, 96, 96, 98, 102, 254, 0 }, // 76 - { 198, 238, 254, 254, 214, 198, 198, 0 }, // 77 - { 198, 230, 246, 222, 206, 198, 198, 0 }, // 78 - { 124, 198, 198, 198, 198, 198, 124, 0 }, // 79 - { 252, 102, 102, 124, 96, 96, 240, 0 }, // 80 - { 124, 198, 198, 198, 198, 206, 124, 14 }, // 81 - { 252, 102, 102, 124, 108, 102, 230, 0 }, // 82 - { 60, 102, 48, 24, 12, 102, 60, 0 }, // 83 - { 126, 126, 90, 24, 24, 24, 60, 0 }, // 84 - { 198, 198, 198, 198, 198, 198, 124, 0 }, // 85 - { 198, 198, 198, 198, 198, 108, 56, 0 }, // 86 - { 198, 198, 198, 214, 214, 254, 108, 0 }, // 87 - { 198, 198, 108, 56, 108, 198, 198, 0 }, // 88 - { 102, 102, 102, 60, 24, 24, 60, 0 }, // 89 - { 254, 198, 140, 24, 50, 102, 254, 0 }, // 90 - { 60, 48, 48, 48, 48, 48, 60, 0 }, // 91 - { 192, 96, 48, 24, 12, 6, 2, 0 }, // 92 - { 60, 12, 12, 12, 12, 12, 60, 0 }, // 93 - { 16, 56, 108, 198, 0, 0, 0, 0 }, // 94 - { 0, 0, 0, 0, 0, 0, 0, 255 }, // 95 - { 48, 24, 12, 0, 0, 0, 0, 0 }, // 96 - { 0, 0, 120, 12, 124, 204, 118, 0 }, // 97 - { 224, 96, 124, 102, 102, 102, 220, 0 }, // 98 - { 0, 0, 124, 198, 192, 198, 124, 0 }, // 99 - { 28, 12, 124, 204, 204, 204, 118, 0 }, // 100 - { 0, 0, 124, 198, 254, 192, 124, 0 }, // 101 - { 60, 102, 96, 248, 96, 96, 240, 0 }, // 102 - { 0, 0, 118, 204, 204, 124, 12, 248 }, // 103 - { 224, 96, 108, 118, 102, 102, 230, 0 }, // 104 - { 24, 0, 56, 24, 24, 24, 60, 0 }, // 105 - { 6, 0, 6, 6, 6, 102, 102, 60 }, // 106 - { 224, 96, 102, 108, 120, 108, 230, 0 }, // 107 - { 56, 24, 24, 24, 24, 24, 60, 0 }, // 108 - { 0, 0, 236, 254, 214, 214, 214, 0 }, // 109 - { 0, 0, 220, 102, 102, 102, 102, 0 }, // 110 - { 0, 0, 124, 198, 198, 198, 124, 0 }, // 111 - { 0, 0, 220, 102, 102, 124, 96, 240 }, // 112 - { 0, 0, 118, 204, 204, 124, 12, 30 }, // 113 - { 0, 0, 220, 118, 96, 96, 240, 0 }, // 114 - { 0, 0, 126, 192, 124, 6, 252, 0 }, // 115 - { 48, 48, 252, 48, 48, 54, 28, 0 }, // 116 - { 0, 0, 204, 204, 204, 204, 118, 0 }, // 117 - { 0, 0, 198, 198, 198, 108, 56, 0 }, // 118 - { 0, 0, 198, 214, 214, 254, 108, 0 }, // 119 - { 0, 0, 198, 108, 56, 108, 198, 0 }, // 120 - { 0, 0, 198, 198, 198, 126, 6, 252 }, // 121 - { 0, 0, 126, 76, 24, 50, 126, 0 }, // 122 - { 14, 24, 24, 112, 24, 24, 14, 0 }, // 123 - { 24, 24, 24, 24, 24, 24, 24, 0 }, // 124 - { 112, 24, 24, 14, 24, 24, 112, 0 }, // 125 - { 118, 220, 0, 0, 0, 0, 0, 0 }, // 126 - { 0, 16, 56, 108, 198, 198, 254, 0 }, // 127 - { 124, 198, 192, 192, 198, 124, 12, 120 }, // 128 - { 204, 0, 204, 204, 204, 204, 118, 0 }, // 129 - { 12, 24, 124, 198, 254, 192, 124, 0 }, // 130 - { 124, 130, 120, 12, 124, 204, 118, 0 }, // 131 - { 198, 0, 120, 12, 124, 204, 118, 0 }, // 132 - { 48, 24, 120, 12, 124, 204, 118, 0 }, // 133 - { 48, 48, 120, 12, 124, 204, 118, 0 }, // 134 - { 0, 0, 126, 192, 192, 126, 12, 56 }, // 135 - { 124, 130, 124, 198, 254, 192, 124, 0 }, // 136 - { 198, 0, 124, 198, 254, 192, 124, 0 }, // 137 - { 48, 24, 124, 198, 254, 192, 124, 0 }, // 138 - { 102, 0, 56, 24, 24, 24, 60, 0 }, // 139 - { 124, 130, 56, 24, 24, 24, 60, 0 }, // 140 - { 48, 24, 0, 56, 24, 24, 60, 0 }, // 141 - { 198, 56, 108, 198, 254, 198, 198, 0 }, // 142 - { 56, 108, 124, 198, 254, 198, 198, 0 }, // 143 - { 24, 48, 254, 192, 248, 192, 254, 0 }, // 144 - { 0, 0, 126, 18, 254, 144, 254, 0 }, // 145 - { 62, 108, 204, 254, 204, 204, 206, 0 }, // 146 - { 124, 130, 124, 198, 198, 198, 124, 0 }, // 147 - { 198, 0, 124, 198, 198, 198, 124, 0 }, // 148 - { 48, 24, 124, 198, 198, 198, 124, 0 }, // 149 - { 120, 132, 0, 204, 204, 204, 118, 0 }, // 150 - { 96, 48, 204, 204, 204, 204, 118, 0 }, // 151 - { 198, 0, 198, 198, 198, 126, 6, 252 }, // 152 - { 198, 56, 108, 198, 198, 108, 56, 0 }, // 153 - { 198, 0, 198, 198, 198, 198, 124, 0 }, // 154 - { 0, 2, 124, 206, 214, 230, 124, 128 }, // 155 - { 56, 108, 100, 240, 96, 102, 252, 0 }, // 156 - { 58, 108, 206, 214, 230, 108, 184, 0 }, // 157 - { 0, 198, 108, 56, 108, 198, 0, 0 }, // 158 - { 14, 27, 24, 60, 24, 216, 112, 0 }, // 159 - { 24, 48, 120, 12, 124, 204, 118, 0 }, // 160 - { 12, 24, 0, 56, 24, 24, 60, 0 }, // 161 - { 12, 24, 124, 198, 198, 198, 124, 0 }, // 162 - { 24, 48, 204, 204, 204, 204, 118, 0 }, // 163 - { 118, 220, 0, 220, 102, 102, 102, 0 }, // 164 - { 118, 220, 0, 230, 246, 222, 206, 0 }, // 165 - { 60, 108, 108, 62, 0, 126, 0, 0 }, // 166 - { 56, 108, 108, 56, 0, 124, 0, 0 }, // 167 - { 24, 0, 24, 24, 48, 99, 62, 0 }, // 168 - { 126, 129, 185, 165, 185, 165, 129, 126 }, // 169 - { 0, 0, 0, 254, 6, 6, 0, 0 }, // 170 - { 99, 230, 108, 126, 51, 102, 204, 15 }, // 171 - { 99, 230, 108, 122, 54, 106, 223, 6 }, // 172 - { 24, 0, 24, 24, 60, 60, 24, 0 }, // 173 - { 0, 51, 102, 204, 102, 51, 0, 0 }, // 174 - { 0, 204, 102, 51, 102, 204, 0, 0 }, // 175 - { 34, 136, 34, 136, 34, 136, 34, 136 }, // 176 - { 85, 170, 85, 170, 85, 170, 85, 170 }, // 177 - { 119, 221, 119, 221, 119, 221, 119, 221 }, // 178 - { 24, 24, 24, 24, 24, 24, 24, 24 }, // 179 - { 24, 24, 56, 248, 56, 24, 24, 24 }, // 180 - { 48, 96, 56, 108, 198, 254, 198, 0 }, // 181 - { 124, 130, 56, 108, 198, 254, 198, 0 }, // 182 - { 24, 12, 56, 108, 198, 254, 198, 0 }, // 183 - { 126, 129, 157, 161, 161, 157, 129, 126 }, // 184 - { 54, 54, 246, 6, 246, 54, 54, 54 }, // 185 - { 54, 54, 54, 54, 54, 54, 54, 54 }, // 186 - { 0, 0, 254, 6, 246, 54, 54, 54 }, // 187 - { 54, 54, 246, 6, 254, 0, 0, 0 }, // 188 - { 24, 24, 126, 192, 192, 126, 24, 24 }, // 189 - { 102, 102, 60, 126, 24, 126, 24, 24 }, // 190 - { 0, 0, 0, 240, 56, 24, 24, 24 }, // 191 - { 24, 24, 28, 15, 0, 0, 0, 0 }, // 192 - { 24, 24, 60, 255, 0, 0, 0, 0 }, // 193 - { 0, 0, 0, 255, 60, 24, 24, 24 }, // 194 - { 48, 48, 56, 63, 56, 48, 48, 48 }, // 195 - { 0, 0, 0, 255, 0, 0, 0, 0 }, // 196 - { 24, 24, 24, 60, 231, 60, 24, 24 }, // 197 - { 240, 120, 120, 120, 60, 60, 60, 28 }, // 198 - { 30, 60, 60, 60, 120, 120, 120, 112 }, // 199 - { 15, 63, 63, 120, 120, 0, 1, 3 }, // 200 - { 192, 224, 240, 240, 240, 240, 240, 224 }, // 201 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // 202 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // 203 - { 30, 30, 14, 15, 15, 7, 7, 0 }, // 204 - { 240, 240, 224, 224, 192, 192, 192, 0 }, // 205 - { 6, 13, 27, 55, 47, 127, 126, 30 }, // 206 - { 0, 252, 255, 255, 143, 119, 243, 3 }, // 207 - { 0, 1, 7, 143, 143, 207, 207, 199 }, // 208 - { 0, 248, 254, 254, 31, 15, 192, 248 }, // 209 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // 210 - { 0, 0, 0, 0, 0, 0, 0, 0 }, // 211 - { 30, 30, 30, 31, 15, 7, 7, 1 }, // 212 - { 3, 3, 3, 7, 143, 255, 254, 252 }, // 213 - { 195, 192, 192, 207, 143, 7, 7, 1 }, // 214 - { 254, 255, 31, 15, 143, 254, 254, 248 }, // 215 - { 102, 0, 60, 24, 24, 24, 60, 0 }, // 216 - { 24, 24, 56, 240, 0, 0, 0, 0 }, // 217 - { 0, 0, 0, 15, 28, 24, 24, 24 }, // 218 - { 255, 255, 255, 255, 255, 255, 255, 255 }, // 219 - { 0, 0, 0, 0, 255, 255, 255, 255 }, // 220 - { 24, 24, 24, 0, 0, 24, 24, 24 }, // 221 - { 48, 24, 60, 24, 24, 24, 60, 0 }, // 222 - { 255, 255, 255, 255, 0, 0, 0, 0 }, // 223 - { 0, 0, 0, 0, 0, 0, 0, 255 }, // 224 - { 0, 0, 0, 0, 0, 255, 0, 255 }, // 225 - { 0, 0, 0, 255, 0, 255, 0, 255 }, // 226 - { 0, 255, 0, 255, 0, 255, 0, 255 }, // 227 - { 0, 255, 0, 255, 0, 255, 0, 0 }, // 228 - { 0, 255, 0, 255, 0, 0, 0, 0 }, // 229 - { 0, 255, 0, 0, 0, 0, 0, 0 }, // 230 - { 224, 128, 0, 0, 0, 0, 128, 224 }, // 231 - { 248, 254, 255, 255, 255, 255, 254, 248 }, // 232 - { 24, 48, 198, 198, 198, 198, 124, 0 }, // 233 - { 124, 130, 0, 198, 198, 198, 124, 0 }, // 234 - { 96, 48, 198, 198, 198, 198, 124, 0 }, // 235 - { 24, 48, 198, 198, 198, 126, 6, 252 }, // 236 - { 12, 24, 102, 102, 60, 24, 60, 0 }, // 237 - { 255, 0, 0, 0, 0, 0, 0, 0 }, // 238 - { 12, 24, 48, 0, 0, 0, 0, 0 }, // 239 - { 0, 0, 0, 126, 0, 0, 0, 0 }, // 240 - { 24, 24, 126, 24, 24, 0, 126, 0 }, // 241 - { 0, 0, 0, 0, 0, 255, 0, 255 }, // 242 - { 225, 50, 228, 58, 246, 42, 95, 134 }, // 243 - { 127, 219, 219, 123, 27, 27, 27, 0 }, // 244 - { 62, 97, 60, 102, 102, 60, 134, 124 }, // 245 - { 0, 24, 0, 126, 0, 24, 0, 0 }, // 246 - { 0, 0, 0, 0, 0, 24, 12, 56 }, // 247 - { 56, 108, 108, 56, 0, 0, 0, 0 }, // 248 - { 0, 198, 0, 0, 0, 0, 0, 0 }, // 249 - { 0, 0, 0, 24, 0, 0, 0, 0 }, // 250 - { 24, 56, 24, 24, 60, 0, 0, 0 }, // 251 - { 120, 12, 56, 12, 120, 0, 0, 0 }, // 252 - { 120, 12, 24, 48, 124, 0, 0, 0 }, // 253 - { 0, 0, 60, 60, 60, 60, 0, 0 }, // 254 - { 0, 0, 0, 0, 0, 0, 0, 0 }}; // 255 - -/* -unsigned char sdl_palette[256][3] = { - { 0, 0, 0 }, // 0 - { 0, 0, 168 }, // 1 - { 0, 168, 0 }, // 2 - { 0, 168, 168 }, // 3 - { 168, 0, 0 }, // 4 - { 168, 0, 168 }, // 5 - { 168, 84, 0 }, // 6 - { 168, 168, 168 }, // 7 - { 84, 84, 84 }, // 8 - { 84, 84, 252 }, // 9 - { 84, 252, 84 }, // 10 - { 84, 252, 252 }, // 11 - { 252, 84, 84 }, // 12 - { 252, 84, 252 }, // 13 - { 252, 252, 84 }, // 14 - { 252, 252, 252 }, // 15 - { 0, 0, 0 }, // 16 - { 20, 20, 20 }, // 17 - { 32, 32, 32 }, // 18 - { 44, 44, 44 }, // 19 - { 56, 56, 56 }, // 20 - { 68, 68, 68 }, // 21 - { 80, 80, 80 }, // 22 - { 96, 96, 96 }, // 23 - { 112, 112, 112 }, // 24 - { 128, 128, 128 }, // 25 - { 144, 144, 144 }, // 26 - { 160, 160, 160 }, // 27 - { 180, 180, 180 }, // 28 - { 200, 200, 200 }, // 29 - { 224, 224, 224 }, // 30 - { 252, 252, 252 }, // 31 - { 0, 0, 252 }, // 32 - { 64, 0, 252 }, // 33 - { 124, 0, 252 }, // 34 - { 188, 0, 252 }, // 35 - { 252, 0, 252 }, // 36 - { 252, 0, 188 }, // 37 - { 252, 0, 124 }, // 38 - { 252, 0, 64 }, // 39 - { 252, 0, 0 }, // 40 - { 252, 64, 0 }, // 41 - { 252, 124, 0 }, // 42 - { 252, 188, 0 }, // 43 - { 252, 252, 0 }, // 44 - { 188, 252, 0 }, // 45 - { 124, 252, 0 }, // 46 - { 64, 252, 0 }, // 47 - { 0, 252, 0 }, // 48 - { 0, 252, 64 }, // 49 - { 0, 252, 124 }, // 50 - { 0, 252, 188 }, // 51 - { 0, 252, 252 }, // 52 - { 0, 188, 252 }, // 53 - { 0, 124, 252 }, // 54 - { 0, 64, 252 }, // 55 - { 124, 124, 252 }, // 56 - { 156, 124, 252 }, // 57 - { 188, 124, 252 }, // 58 - { 220, 124, 252 }, // 59 - { 252, 124, 252 }, // 60 - { 252, 124, 220 }, // 61 - { 252, 124, 188 }, // 62 - { 252, 124, 156 }, // 63 - { 252, 124, 124 }, // 64 - { 252, 156, 124 }, // 65 - { 252, 188, 124 }, // 66 - { 252, 220, 124 }, // 67 - { 252, 252, 124 }, // 68 - { 220, 252, 124 }, // 69 - { 188, 252, 124 }, // 70 - { 156, 252, 124 }, // 71 - { 124, 252, 124 }, // 72 - { 124, 252, 156 }, // 73 - { 124, 252, 188 }, // 74 - { 124, 252, 220 }, // 75 - { 124, 252, 252 }, // 76 - { 124, 220, 252 }, // 77 - { 124, 188, 252 }, // 78 - { 124, 156, 252 }, // 79 - { 180, 180, 252 }, // 80 - { 196, 180, 252 }, // 81 - { 216, 180, 252 }, // 82 - { 232, 180, 252 }, // 83 - { 252, 180, 252 }, // 84 - { 252, 180, 232 }, // 85 - { 252, 180, 216 }, // 86 - { 252, 180, 196 }, // 87 - { 252, 180, 180 }, // 88 - { 252, 196, 180 }, // 89 - { 252, 216, 180 }, // 90 - { 252, 232, 180 }, // 91 - { 252, 252, 180 }, // 92 - { 232, 252, 180 }, // 93 - { 216, 252, 180 }, // 94 - { 196, 252, 180 }, // 95 - { 180, 252, 180 }, // 96 - { 180, 252, 196 }, // 97 - { 180, 252, 216 }, // 98 - { 180, 252, 232 }, // 99 - { 180, 252, 252 }, // 100 - { 180, 232, 252 }, // 101 - { 180, 216, 252 }, // 102 - { 180, 196, 252 }, // 103 - { 0, 0, 112 }, // 104 - { 28, 0, 112 }, // 105 - { 56, 0, 112 }, // 106 - { 84, 0, 112 }, // 107 - { 112, 0, 112 }, // 108 - { 112, 0, 84 }, // 109 - { 112, 0, 56 }, // 110 - { 112, 0, 28 }, // 111 - { 112, 0, 0 }, // 112 - { 112, 28, 0 }, // 113 - { 112, 56, 0 }, // 114 - { 112, 84, 0 }, // 115 - { 112, 112, 0 }, // 116 - { 84, 112, 0 }, // 117 - { 56, 112, 0 }, // 118 - { 28, 112, 0 }, // 119 - { 0, 112, 0 }, // 120 - { 0, 112, 28 }, // 121 - { 0, 112, 56 }, // 122 - { 0, 112, 84 }, // 123 - { 0, 112, 112 }, // 124 - { 0, 84, 112 }, // 125 - { 0, 56, 112 }, // 126 - { 0, 28, 112 }, // 127 - { 56, 56, 112 }, // 128 - { 68, 56, 112 }, // 129 - { 84, 56, 112 }, // 130 - { 96, 56, 112 }, // 131 - { 112, 56, 112 }, // 132 - { 112, 56, 96 }, // 133 - { 112, 56, 84 }, // 134 - { 112, 56, 68 }, // 135 - { 112, 56, 56 }, // 136 - { 112, 68, 56 }, // 137 - { 112, 84, 56 }, // 138 - { 112, 96, 56 }, // 139 - { 112, 112, 56 }, // 140 - { 96, 112, 56 }, // 141 - { 84, 112, 56 }, // 142 - { 68, 112, 56 }, // 143 - { 56, 112, 56 }, // 144 - { 56, 112, 68 }, // 145 - { 56, 112, 84 }, // 146 - { 56, 112, 96 }, // 147 - { 56, 112, 112 }, // 148 - { 56, 96, 112 }, // 149 - { 56, 84, 112 }, // 150 - { 56, 68, 112 }, // 151 - { 80, 80, 112 }, // 152 - { 88, 80, 112 }, // 153 - { 96, 80, 112 }, // 154 - { 104, 80, 112 }, // 155 - { 112, 80, 112 }, // 156 - { 112, 80, 104 }, // 157 - { 112, 80, 96 }, // 158 - { 112, 80, 88 }, // 159 - { 112, 80, 80 }, // 160 - { 112, 88, 80 }, // 161 - { 112, 96, 80 }, // 162 - { 112, 104, 80 }, // 163 - { 112, 112, 80 }, // 164 - { 104, 112, 80 }, // 165 - { 96, 112, 80 }, // 166 - { 88, 112, 80 }, // 167 - { 80, 112, 80 }, // 168 - { 80, 112, 88 }, // 169 - { 80, 112, 96 }, // 170 - { 80, 112, 104 }, // 171 - { 80, 112, 112 }, // 172 - { 80, 104, 112 }, // 173 - { 80, 96, 112 }, // 174 - { 80, 88, 112 }, // 175 - { 0, 0, 64 }, // 176 - { 16, 0, 64 }, // 177 - { 32, 0, 64 }, // 178 - { 48, 0, 64 }, // 179 - { 64, 0, 64 }, // 180 - { 64, 0, 48 }, // 181 - { 64, 0, 32 }, // 182 - { 64, 0, 16 }, // 183 - { 64, 0, 0 }, // 184 - { 64, 16, 0 }, // 185 - { 64, 32, 0 }, // 186 - { 64, 48, 0 }, // 187 - { 64, 64, 0 }, // 188 - { 48, 64, 0 }, // 189 - { 32, 64, 0 }, // 190 - { 16, 64, 0 }, // 191 - { 0, 64, 0 }, // 192 - { 0, 64, 16 }, // 193 - { 0, 64, 32 }, // 194 - { 0, 64, 48 }, // 195 - { 0, 64, 64 }, // 196 - { 0, 48, 64 }, // 197 - { 0, 32, 64 }, // 198 - { 0, 16, 64 }, // 199 - { 32, 32, 64 }, // 200 - { 40, 32, 64 }, // 201 - { 48, 32, 64 }, // 202 - { 56, 32, 64 }, // 203 - { 64, 32, 64 }, // 204 - { 64, 32, 56 }, // 205 - { 64, 32, 48 }, // 206 - { 64, 32, 40 }, // 207 - { 64, 32, 32 }, // 208 - { 64, 40, 32 }, // 209 - { 64, 48, 32 }, // 210 - { 64, 56, 32 }, // 211 - { 64, 64, 32 }, // 212 - { 56, 64, 32 }, // 213 - { 48, 64, 32 }, // 214 - { 40, 64, 32 }, // 215 - { 32, 64, 32 }, // 216 - { 32, 64, 40 }, // 217 - { 32, 64, 48 }, // 218 - { 32, 64, 56 }, // 219 - { 32, 64, 64 }, // 220 - { 32, 56, 64 }, // 221 - { 32, 48, 64 }, // 222 - { 32, 40, 64 }, // 223 - { 44, 44, 64 }, // 224 - { 48, 44, 64 }, // 225 - { 52, 44, 64 }, // 226 - { 60, 44, 64 }, // 227 - { 64, 44, 64 }, // 228 - { 64, 44, 60 }, // 229 - { 64, 44, 52 }, // 230 - { 64, 44, 48 }, // 231 - { 64, 44, 44 }, // 232 - { 64, 48, 44 }, // 233 - { 64, 52, 44 }, // 234 - { 64, 60, 44 }, // 235 - { 64, 64, 44 }, // 236 - { 60, 64, 44 }, // 237 - { 52, 64, 44 }, // 238 - { 48, 64, 44 }, // 239 - { 44, 64, 44 }, // 240 - { 44, 64, 48 }, // 241 - { 44, 64, 52 }, // 242 - { 44, 64, 60 }, // 243 - { 44, 64, 64 }, // 244 - { 44, 60, 64 }, // 245 - { 44, 52, 64 }, // 246 - { 44, 48, 64 }, // 247 - { 0, 0, 0 }, // 248 - { 0, 0, 0 }, // 249 - { 0, 0, 0 }, // 250 - { 0, 0, 0 }, // 251 - { 0, 0, 0 }, // 252 - { 0, 0, 0 }, // 253 - { 0, 0, 0 }, // 254 - { 112, 97, 108 }}; // 255 -*/ diff --git a/tools/ioemu/gui/sdlkeys.h b/tools/ioemu/gui/sdlkeys.h deleted file mode 100644 index fd1197a5f1..0000000000 --- a/tools/ioemu/gui/sdlkeys.h +++ /dev/null @@ -1,257 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: sdlkeys.h,v 1.2 2002/10/24 21:06:32 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// This file is simply a list of SDL key symbols taken from . -// The order in this file is not important. In sdl.cc, DEF_SDL_KEY() is -// defined as a macro and then it includes this file to fill in all the data in -// its key mapping table. -// -// The symbols, such as SDLK_RETURN, are used for two purposes. They -// are converted into a string (by the # operator in processor), which is -// compared to the host key name in the keymap file. Also, the value of -// the symbol is inserted into the key mapping table. Then the value is -// compared with the keysym field of each key up/down event as it arrives. -// -// If you get undefined symbol errors in this file, it must mean that -// your SDL library version doesn't define those same SDLK_* symbols in -// . You can't fix it with #ifdef SDLK_SYM because -// they are enums, so you'll just have to comment out the offending line. -// The list was generated using symbols from SDL 1.2.3. - -DEF_SDL_KEY( SDLK_UNKNOWN ) -DEF_SDL_KEY( SDLK_FIRST ) -DEF_SDL_KEY( SDLK_BACKSPACE ) -DEF_SDL_KEY( SDLK_TAB ) -DEF_SDL_KEY( SDLK_CLEAR ) -DEF_SDL_KEY( SDLK_RETURN ) -DEF_SDL_KEY( SDLK_PAUSE ) -DEF_SDL_KEY( SDLK_ESCAPE ) -DEF_SDL_KEY( SDLK_SPACE ) -DEF_SDL_KEY( SDLK_EXCLAIM ) -DEF_SDL_KEY( SDLK_QUOTEDBL ) -DEF_SDL_KEY( SDLK_HASH ) -DEF_SDL_KEY( SDLK_DOLLAR ) -DEF_SDL_KEY( SDLK_AMPERSAND ) -DEF_SDL_KEY( SDLK_QUOTE ) -DEF_SDL_KEY( SDLK_LEFTPAREN ) -DEF_SDL_KEY( SDLK_RIGHTPAREN ) -DEF_SDL_KEY( SDLK_ASTERISK ) -DEF_SDL_KEY( SDLK_PLUS ) -DEF_SDL_KEY( SDLK_COMMA ) -DEF_SDL_KEY( SDLK_MINUS ) -DEF_SDL_KEY( SDLK_PERIOD ) -DEF_SDL_KEY( SDLK_SLASH ) -DEF_SDL_KEY( SDLK_0 ) -DEF_SDL_KEY( SDLK_1 ) -DEF_SDL_KEY( SDLK_2 ) -DEF_SDL_KEY( SDLK_3 ) -DEF_SDL_KEY( SDLK_4 ) -DEF_SDL_KEY( SDLK_5 ) -DEF_SDL_KEY( SDLK_6 ) -DEF_SDL_KEY( SDLK_7 ) -DEF_SDL_KEY( SDLK_8 ) -DEF_SDL_KEY( SDLK_9 ) -DEF_SDL_KEY( SDLK_COLON ) -DEF_SDL_KEY( SDLK_SEMICOLON ) -DEF_SDL_KEY( SDLK_LESS ) -DEF_SDL_KEY( SDLK_EQUALS ) -DEF_SDL_KEY( SDLK_GREATER ) -DEF_SDL_KEY( SDLK_QUESTION ) -DEF_SDL_KEY( SDLK_AT ) -DEF_SDL_KEY( /* ) -DEF_SDL_KEY( Skip uppercase letters ) -DEF_SDL_KEY( */ ) -DEF_SDL_KEY( SDLK_LEFTBRACKET ) -DEF_SDL_KEY( SDLK_BACKSLASH ) -DEF_SDL_KEY( SDLK_RIGHTBRACKET ) -DEF_SDL_KEY( SDLK_CARET ) -DEF_SDL_KEY( SDLK_UNDERSCORE ) -DEF_SDL_KEY( SDLK_BACKQUOTE ) -DEF_SDL_KEY( SDLK_a ) -DEF_SDL_KEY( SDLK_b ) -DEF_SDL_KEY( SDLK_c ) -DEF_SDL_KEY( SDLK_d ) -DEF_SDL_KEY( SDLK_e ) -DEF_SDL_KEY( SDLK_f ) -DEF_SDL_KEY( SDLK_g ) -DEF_SDL_KEY( SDLK_h ) -DEF_SDL_KEY( SDLK_i ) -DEF_SDL_KEY( SDLK_j ) -DEF_SDL_KEY( SDLK_k ) -DEF_SDL_KEY( SDLK_l ) -DEF_SDL_KEY( SDLK_m ) -DEF_SDL_KEY( SDLK_n ) -DEF_SDL_KEY( SDLK_o ) -DEF_SDL_KEY( SDLK_p ) -DEF_SDL_KEY( SDLK_q ) -DEF_SDL_KEY( SDLK_r ) -DEF_SDL_KEY( SDLK_s ) -DEF_SDL_KEY( SDLK_t ) -DEF_SDL_KEY( SDLK_u ) -DEF_SDL_KEY( SDLK_v ) -DEF_SDL_KEY( SDLK_w ) -DEF_SDL_KEY( SDLK_x ) -DEF_SDL_KEY( SDLK_y ) -DEF_SDL_KEY( SDLK_z ) -DEF_SDL_KEY( SDLK_DELETE ) -DEF_SDL_KEY( SDLK_WORLD_0 ) -DEF_SDL_KEY( SDLK_WORLD_1 ) -DEF_SDL_KEY( SDLK_WORLD_2 ) -DEF_SDL_KEY( SDLK_WORLD_3 ) -DEF_SDL_KEY( SDLK_WORLD_4 ) -DEF_SDL_KEY( SDLK_WORLD_5 ) -DEF_SDL_KEY( SDLK_WORLD_6 ) -DEF_SDL_KEY( SDLK_WORLD_7 ) -DEF_SDL_KEY( SDLK_WORLD_8 ) -DEF_SDL_KEY( SDLK_WORLD_9 ) -DEF_SDL_KEY( SDLK_WORLD_10 ) -DEF_SDL_KEY( SDLK_WORLD_11 ) -DEF_SDL_KEY( SDLK_WORLD_12 ) -DEF_SDL_KEY( SDLK_WORLD_13 ) -DEF_SDL_KEY( SDLK_WORLD_14 ) -DEF_SDL_KEY( SDLK_WORLD_15 ) -DEF_SDL_KEY( SDLK_WORLD_16 ) -DEF_SDL_KEY( SDLK_WORLD_17 ) -DEF_SDL_KEY( SDLK_WORLD_18 ) -DEF_SDL_KEY( SDLK_WORLD_19 ) -DEF_SDL_KEY( SDLK_WORLD_20 ) -DEF_SDL_KEY( SDLK_WORLD_21 ) -DEF_SDL_KEY( SDLK_WORLD_22 ) -DEF_SDL_KEY( SDLK_WORLD_23 ) -DEF_SDL_KEY( SDLK_WORLD_24 ) -DEF_SDL_KEY( SDLK_WORLD_25 ) -DEF_SDL_KEY( SDLK_WORLD_26 ) -DEF_SDL_KEY( SDLK_WORLD_27 ) -DEF_SDL_KEY( SDLK_WORLD_28 ) -DEF_SDL_KEY( SDLK_WORLD_29 ) -DEF_SDL_KEY( SDLK_WORLD_30 ) -DEF_SDL_KEY( SDLK_WORLD_31 ) -DEF_SDL_KEY( SDLK_WORLD_32 ) -DEF_SDL_KEY( SDLK_WORLD_33 ) -DEF_SDL_KEY( SDLK_WORLD_34 ) -DEF_SDL_KEY( SDLK_WORLD_35 ) -DEF_SDL_KEY( SDLK_WORLD_36 ) -DEF_SDL_KEY( SDLK_WORLD_37 ) -DEF_SDL_KEY( SDLK_WORLD_38 ) -DEF_SDL_KEY( SDLK_WORLD_39 ) -DEF_SDL_KEY( SDLK_WORLD_40 ) -DEF_SDL_KEY( SDLK_WORLD_41 ) -DEF_SDL_KEY( SDLK_WORLD_42 ) -DEF_SDL_KEY( SDLK_WORLD_43 ) -DEF_SDL_KEY( SDLK_WORLD_44 ) -DEF_SDL_KEY( SDLK_WORLD_45 ) -DEF_SDL_KEY( SDLK_WORLD_46 ) -DEF_SDL_KEY( SDLK_WORLD_47 ) -DEF_SDL_KEY( SDLK_WORLD_48 ) -DEF_SDL_KEY( SDLK_WORLD_49 ) -DEF_SDL_KEY( SDLK_WORLD_50 ) -DEF_SDL_KEY( SDLK_WORLD_51 ) -DEF_SDL_KEY( SDLK_WORLD_52 ) -DEF_SDL_KEY( SDLK_WORLD_53 ) -DEF_SDL_KEY( SDLK_WORLD_54 ) -DEF_SDL_KEY( SDLK_WORLD_55 ) -DEF_SDL_KEY( SDLK_WORLD_56 ) -DEF_SDL_KEY( SDLK_WORLD_57 ) -DEF_SDL_KEY( SDLK_WORLD_58 ) -DEF_SDL_KEY( SDLK_WORLD_59 ) -DEF_SDL_KEY( SDLK_WORLD_60 ) -DEF_SDL_KEY( SDLK_WORLD_61 ) -DEF_SDL_KEY( SDLK_WORLD_62 ) -DEF_SDL_KEY( SDLK_WORLD_63 ) -DEF_SDL_KEY( SDLK_WORLD_64 ) -DEF_SDL_KEY( SDLK_WORLD_65 ) -DEF_SDL_KEY( SDLK_WORLD_66 ) -DEF_SDL_KEY( SDLK_WORLD_67 ) -DEF_SDL_KEY( SDLK_WORLD_68 ) -DEF_SDL_KEY( SDLK_WORLD_69 ) -DEF_SDL_KEY( SDLK_WORLD_70 ) -DEF_SDL_KEY( SDLK_WORLD_71 ) -DEF_SDL_KEY( SDLK_WORLD_72 ) -DEF_SDL_KEY( SDLK_WORLD_73 ) -DEF_SDL_KEY( SDLK_WORLD_74 ) -DEF_SDL_KEY( SDLK_WORLD_75 ) -DEF_SDL_KEY( SDLK_WORLD_76 ) -DEF_SDL_KEY( SDLK_WORLD_77 ) -DEF_SDL_KEY( SDLK_WORLD_78 ) -DEF_SDL_KEY( SDLK_WORLD_79 ) -DEF_SDL_KEY( SDLK_WORLD_80 ) -DEF_SDL_KEY( SDLK_WORLD_81 ) -DEF_SDL_KEY( SDLK_WORLD_82 ) -DEF_SDL_KEY( SDLK_WORLD_83 ) -DEF_SDL_KEY( SDLK_WORLD_84 ) -DEF_SDL_KEY( SDLK_WORLD_85 ) -DEF_SDL_KEY( SDLK_WORLD_86 ) -DEF_SDL_KEY( SDLK_WORLD_87 ) -DEF_SDL_KEY( SDLK_WORLD_88 ) -DEF_SDL_KEY( SDLK_WORLD_89 ) -DEF_SDL_KEY( SDLK_WORLD_90 ) -DEF_SDL_KEY( SDLK_WORLD_91 ) -DEF_SDL_KEY( SDLK_WORLD_92 ) -DEF_SDL_KEY( SDLK_WORLD_93 ) -DEF_SDL_KEY( SDLK_WORLD_94 ) -DEF_SDL_KEY( SDLK_WORLD_95 ) -DEF_SDL_KEY( SDLK_KP0 ) -DEF_SDL_KEY( SDLK_KP1 ) -DEF_SDL_KEY( SDLK_KP2 ) -DEF_SDL_KEY( SDLK_KP3 ) -DEF_SDL_KEY( SDLK_KP4 ) -DEF_SDL_KEY( SDLK_KP5 ) -DEF_SDL_KEY( SDLK_KP6 ) -DEF_SDL_KEY( SDLK_KP7 ) -DEF_SDL_KEY( SDLK_KP8 ) -DEF_SDL_KEY( SDLK_KP9 ) -DEF_SDL_KEY( SDLK_KP_PERIOD ) -DEF_SDL_KEY( SDLK_KP_DIVIDE ) -DEF_SDL_KEY( SDLK_KP_MULTIPLY ) -DEF_SDL_KEY( SDLK_KP_MINUS ) -DEF_SDL_KEY( SDLK_KP_PLUS ) -DEF_SDL_KEY( SDLK_KP_ENTER ) -DEF_SDL_KEY( SDLK_KP_EQUALS ) -DEF_SDL_KEY( SDLK_UP ) -DEF_SDL_KEY( SDLK_DOWN ) -DEF_SDL_KEY( SDLK_RIGHT ) -DEF_SDL_KEY( SDLK_LEFT ) -DEF_SDL_KEY( SDLK_INSERT ) -DEF_SDL_KEY( SDLK_HOME ) -DEF_SDL_KEY( SDLK_END ) -DEF_SDL_KEY( SDLK_PAGEUP ) -DEF_SDL_KEY( SDLK_PAGEDOWN ) -DEF_SDL_KEY( SDLK_F1 ) -DEF_SDL_KEY( SDLK_F2 ) -DEF_SDL_KEY( SDLK_F3 ) -DEF_SDL_KEY( SDLK_F4 ) -DEF_SDL_KEY( SDLK_F5 ) -DEF_SDL_KEY( SDLK_F6 ) -DEF_SDL_KEY( SDLK_F7 ) -DEF_SDL_KEY( SDLK_F8 ) -DEF_SDL_KEY( SDLK_F9 ) -DEF_SDL_KEY( SDLK_F10 ) -DEF_SDL_KEY( SDLK_F11 ) -DEF_SDL_KEY( SDLK_F12 ) -DEF_SDL_KEY( SDLK_F13 ) -DEF_SDL_KEY( SDLK_F14 ) -DEF_SDL_KEY( SDLK_F15 ) -DEF_SDL_KEY( SDLK_NUMLOCK ) -DEF_SDL_KEY( SDLK_CAPSLOCK ) -DEF_SDL_KEY( SDLK_SCROLLOCK ) -DEF_SDL_KEY( SDLK_RSHIFT ) -DEF_SDL_KEY( SDLK_LSHIFT ) -DEF_SDL_KEY( SDLK_RCTRL ) -DEF_SDL_KEY( SDLK_LCTRL ) -DEF_SDL_KEY( SDLK_RALT ) -DEF_SDL_KEY( SDLK_LALT ) -DEF_SDL_KEY( SDLK_RMETA ) -DEF_SDL_KEY( SDLK_LMETA ) -DEF_SDL_KEY( SDLK_LSUPER ) -DEF_SDL_KEY( SDLK_RSUPER ) -DEF_SDL_KEY( SDLK_MODE ) -DEF_SDL_KEY( SDLK_COMPOSE ) -DEF_SDL_KEY( SDLK_HELP ) -DEF_SDL_KEY( SDLK_PRINT ) -DEF_SDL_KEY( SDLK_SYSREQ ) -DEF_SDL_KEY( SDLK_BREAK ) -DEF_SDL_KEY( SDLK_MENU ) -DEF_SDL_KEY( SDLK_POWER ) -DEF_SDL_KEY( SDLK_EURO ) -DEF_SDL_KEY( SDLK_UNDO ) diff --git a/tools/ioemu/gui/siminterface.cc b/tools/ioemu/gui/siminterface.cc deleted file mode 100644 index 0284e6b1d7..0000000000 --- a/tools/ioemu/gui/siminterface.cc +++ /dev/null @@ -1,1411 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: siminterface.cc,v 1.105 2004/01/05 22:18:01 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// See siminterface.h for description of the siminterface concept. -// Basically, the siminterface is visible from both the simulator and -// the configuration user interface, and allows them to talk to each other. - -#include "bochs.h" - -bx_simulator_interface_c *SIM = NULL; -logfunctions *siminterface_log = NULL; -#define LOG_THIS siminterface_log-> - -// bx_simulator_interface just defines the interface that the Bochs simulator -// and the gui will use to talk to each other. None of the methods of -// bx_simulator_interface are implemented; they are all virtual. The -// bx_real_sim_c class is a child of bx_simulator_interface_c, and it -// implements all the methods. The idea is that a gui needs to know only -// definition of bx_simulator_interface to talk to Bochs. The gui should -// not need to include bochs.h. -// -// I made this separation to ensure that all guis use the siminterface to do -// access bochs internals, instead of accessing things like -// bx_keyboard.s.internal_buffer[4] (or whatever) directly. -Bryce -// - -class bx_real_sim_c : public bx_simulator_interface_c { - bxevent_handler bxevent_callback; - void *bxevent_callback_data; - const char *registered_ci_name; - config_interface_callback_t ci_callback; - void *ci_callback_data; - int init_done; - bx_param_c **param_registry; - int registry_alloc_size; - int enabled; - // save context to jump to if we must quit unexpectedly - jmp_buf *quit_context; - int exit_code; -public: - bx_real_sim_c (); - virtual ~bx_real_sim_c (); - virtual void set_quit_context (jmp_buf *context) { quit_context = context; } - virtual int get_init_done () { return init_done; } - virtual int set_init_done (int n) { init_done = n; return 0;} - virtual void get_param_id_range (int *min, int *max) { - *min = BXP_NULL; - *max = BXP_THIS_IS_THE_LAST-1; - } - virtual int register_param (bx_id id, bx_param_c *it); - virtual void reset_all_param (); - virtual bx_param_c *get_param (bx_id id); - virtual bx_param_num_c *get_param_num (bx_id id); - virtual bx_param_string_c *get_param_string (bx_id id); - virtual bx_param_bool_c *get_param_bool (bx_id id); - virtual bx_param_enum_c *get_param_enum (bx_id id); - virtual int get_n_log_modules (); - virtual char *get_prefix (int mod); - virtual int get_log_action (int mod, int level); - virtual void set_log_action (int mod, int level, int action); - virtual char *get_action_name (int action); - virtual int get_default_log_action (int level) { - return logfunctions::get_default_action (level); - } - virtual void set_default_log_action (int level, int action) { - logfunctions::set_default_action (level, action); - } - virtual const char *get_log_level_name (int level); - virtual int get_max_log_level (); - virtual void quit_sim (int code); - virtual int get_exit_code () { return exit_code; } - virtual int get_default_rc (char *path, int len); - virtual int read_rc (char *path); - virtual int write_rc (char *path, int overwrite); - virtual int get_log_file (char *path, int len); - virtual int set_log_file (char *path); - virtual int get_log_prefix (char *prefix, int len); - virtual int set_log_prefix (char *prefix); - virtual int get_debugger_log_file (char *path, int len); - virtual int set_debugger_log_file (char *path); - virtual int get_floppy_options (int drive, bx_floppy_options *out); - virtual int get_cdrom_options (int drive, bx_atadevice_options *out, int *device = NULL); - virtual char *get_floppy_type_name (int type); - virtual void set_notify_callback (bxevent_handler func, void *arg); - virtual void get_notify_callback (bxevent_handler *func, void **arg); - virtual BxEvent* sim_to_ci_event (BxEvent *event); - virtual int log_msg (const char *prefix, int level, const char *msg); - virtual int ask_param (bx_id which); - // ask the user for a pathname - virtual int ask_filename (char *filename, int maxlen, char *prompt, char *the_default, int flags); - // called at a regular interval, currently by the keyboard handler. - virtual void periodic (); - virtual int create_disk_image (const char *filename, int sectors, bx_bool overwrite); - virtual void refresh_ci (); - virtual void refresh_vga () { - // maybe need to check if something has been initialized yet? - DEV_vga_refresh(); - } - virtual void handle_events () { - // maybe need to check if something has been initialized yet? - bx_gui->handle_events (); - } - // find first hard drive or cdrom - bx_param_c *get_first_atadevice (Bit32u search_type); - bx_param_c *get_first_cdrom () { - return get_first_atadevice (BX_ATA_DEVICE_CDROM); - } - bx_param_c *get_first_hd () { - return get_first_atadevice (BX_ATA_DEVICE_DISK); - } -#if BX_DEBUGGER - virtual void debug_break (); - virtual void debug_interpret_cmd (char *cmd); - virtual char *debug_get_next_command (); - virtual void debug_puts (const char *cmd); -#endif - virtual void register_configuration_interface ( - const char* name, - config_interface_callback_t callback, - void *userdata); - virtual int configuration_interface(const char* name, ci_command_t command); - virtual int begin_simulation (int argc, char *argv[]); - virtual void set_sim_thread_func (is_sim_thread_func_t func) {} - virtual bool is_sim_thread (); - bool wxsel; - virtual bool is_wx_selected () { return wxsel; } - // provide interface to bx_gui->set_display_mode() method for config - // interfaces to use. - virtual void set_display_mode (disp_mode_t newmode) { - if (bx_gui != NULL) - bx_gui->set_display_mode (newmode); - } - virtual bool test_for_text_console (); -}; - -bx_param_c * -bx_real_sim_c::get_param (bx_id id) -{ - BX_ASSERT (id >= BXP_NULL && id < BXP_THIS_IS_THE_LAST); - int index = (int)id - BXP_NULL; - bx_param_c *retval = param_registry[index]; - if (!retval) - BX_INFO (("get_param can't find id %u", id)); - return retval; -} - -bx_param_num_c * -bx_real_sim_c::get_param_num (bx_id id) { - bx_param_c *generic = get_param(id); - if (generic==NULL) { - BX_PANIC (("get_param_num(%u) could not find a parameter", id)); - return NULL; - } - int type = generic->get_type (); - if (type == BXT_PARAM_NUM || type == BXT_PARAM_BOOL || type == BXT_PARAM_ENUM) - return (bx_param_num_c *)generic; - BX_PANIC (("get_param_num %u could not find an integer parameter with that id", id)); - return NULL; -} - -bx_param_string_c * -bx_real_sim_c::get_param_string (bx_id id) { - bx_param_c *generic = get_param(id); - if (generic==NULL) { - BX_PANIC (("get_param_string(%u) could not find a parameter", id)); - return NULL; - } - if (generic->get_type () == BXT_PARAM_STRING) - return (bx_param_string_c *)generic; - BX_PANIC (("get_param_string %u could not find an integer parameter with that id", id)); - return NULL; -} - -bx_param_bool_c * -bx_real_sim_c::get_param_bool (bx_id id) { - bx_param_c *generic = get_param(id); - if (generic==NULL) { - BX_PANIC (("get_param_bool(%u) could not find a parameter", id)); - return NULL; - } - if (generic->get_type () == BXT_PARAM_BOOL) - return (bx_param_bool_c *)generic; - BX_PANIC (("get_param_bool %u could not find a bool parameter with that id", id)); - return NULL; -} - -bx_param_enum_c * -bx_real_sim_c::get_param_enum (bx_id id) { - bx_param_c *generic = get_param(id); - if (generic==NULL) { - BX_PANIC (("get_param_enum(%u) could not find a parameter", id)); - return NULL; - } - if (generic->get_type () == BXT_PARAM_ENUM) - return (bx_param_enum_c *)generic; - BX_PANIC (("get_param_enum %u could not find a enum parameter with that id", id)); - return NULL; -} - -void bx_init_siminterface () -{ - siminterface_log = new logfunctions (); - siminterface_log->put ("CTRL"); - siminterface_log->settype(CTRLLOG); - if (SIM == NULL) - SIM = new bx_real_sim_c(); -} - -bx_simulator_interface_c::bx_simulator_interface_c () -{ -} - -bx_real_sim_c::bx_real_sim_c () -{ - bxevent_callback = NULL; - bxevent_callback_data = NULL; - ci_callback = NULL; - ci_callback_data = NULL; - is_sim_thread_func = NULL; - wxsel = false; - - enabled = 1; - int i; - init_done = 0; - registry_alloc_size = BXP_THIS_IS_THE_LAST - BXP_NULL; - param_registry = new bx_param_c* [registry_alloc_size]; - for (i=0; i= BXP_NULL && id < BXP_THIS_IS_THE_LAST); - int index = (int)id - BXP_NULL; - if (this->param_registry[index] != NULL) { - BX_INFO (("register_param is overwriting parameter id %d", id)); - } - this->param_registry[index] = it; - return 0; -} - -void -bx_real_sim_c::reset_all_param () -{ - bx_reset_options (); -} - -int -bx_real_sim_c::get_n_log_modules () -{ - return io->get_n_logfns (); -} - -char * -bx_real_sim_c::get_prefix (int mod) -{ - logfunc_t *logfn = io->get_logfn (mod); - return logfn->getprefix (); -} - -int -bx_real_sim_c::get_log_action (int mod, int level) -{ - logfunc_t *logfn = io->get_logfn (mod); - return logfn->getonoff (level); -} - -void -bx_real_sim_c::set_log_action (int mod, int level, int action) -{ - // normal - if (mod >= 0) { - logfunc_t *logfn = io->get_logfn (mod); - logfn->setonoff (level, action); - return; - } - // if called with mod<0 loop over all - int nmod = get_n_log_modules (); - for (mod=0; modgetaction (action); -} - -const char * -bx_real_sim_c::get_log_level_name (int level) -{ - return io->getlevel (level); -} - -int -bx_real_sim_c::get_max_log_level () -{ - return N_LOGLEV; -} - -void -bx_real_sim_c::quit_sim (int code) { - BX_INFO (("quit_sim called with exit code %d", code)); - exit_code = code; - // use longjmp to quit cleanly, no matter where in the stack we are. - //fprintf (stderr, "using longjmp() to jump directly to the quit context!\n"); - if (quit_context != NULL) { - longjmp (*quit_context, 1); - BX_PANIC (("in bx_real_sim_c::quit_sim, longjmp should never return")); - } - if (SIM->is_wx_selected ()) { - // in wxWindows, the whole simulator is running in a separate thread. - // our only job is to end the thread as soon as possible, NOT to shut - // down the whole application with an exit. - BX_CPU(0)->async_event = 1; - BX_CPU(0)->kill_bochs_request = 1; - // the cpu loop will exit very soon after this condition is set. - } else { - // just a single thread. Use exit() to stop the application. - if (!code) - BX_PANIC (("Quit simulation command")); - ::exit (exit_code); - } -} - -int -bx_real_sim_c::get_default_rc (char *path, int len) -{ - char *rc = bx_find_bochsrc (); - if (rc == NULL) return -1; - strncpy (path, rc, len); - path[len-1] = 0; - return 0; -} - -int -bx_real_sim_c::read_rc (char *rc) -{ - return bx_read_configuration (rc); -} - -// return values: -// 0: written ok -// -1: failed -// -2: already exists, and overwrite was off -int -bx_real_sim_c::write_rc (char *rc, int overwrite) -{ - return bx_write_configuration (rc, overwrite); -} - -int -bx_real_sim_c::get_log_file (char *path, int len) -{ - strncpy (path, bx_options.log.Ofilename->getptr (), len); - return 0; -} - -int -bx_real_sim_c::set_log_file (char *path) -{ - bx_options.log.Ofilename->set (path); - return 0; -} - -int -bx_real_sim_c::get_log_prefix (char *prefix, int len) -{ - strncpy (prefix, bx_options.log.Oprefix->getptr (), len); - return 0; -} - -int -bx_real_sim_c::set_log_prefix (char *prefix) -{ - bx_options.log.Oprefix->set (prefix); - return 0; -} - -int -bx_real_sim_c::get_debugger_log_file (char *path, int len) -{ - strncpy (path, bx_options.log.Odebugger_filename->getptr (), len); - return 0; -} - -int -bx_real_sim_c::set_debugger_log_file (char *path) -{ - bx_options.log.Odebugger_filename->set (path); - return 0; -} - -int -bx_real_sim_c::get_floppy_options (int drive, bx_floppy_options *out) -{ - *out = (drive==0)? bx_options.floppya : bx_options.floppyb; - return 0; -} - -int -bx_real_sim_c::get_cdrom_options (int level, bx_atadevice_options *out, int *where) -{ - for (Bit8u channel=0; channelget() == BX_ATA_DEVICE_CDROM) { - if (level==0) { - *out = bx_options.atadevice[channel][device]; - if (where != NULL) *where=(channel*2)+device; - return 1; - } - else level--; - } - } - } - return 0; -} - -char *bochs_start_names[] = { "quick", "load", "edit", "run" }; -int n_bochs_start_names = 3; - -char *floppy_type_names[] = { "none", "1.2M", "1.44M", "2.88M", "720K", "360K", "160K", "180K", "320K", NULL }; -int floppy_type_n_sectors[] = { -1, 80*2*15, 80*2*18, 80*2*36, 80*2*9, 40*2*9, 40*1*8, 40*1*9, 40*2*8 }; -int n_floppy_type_names = 9; - -char *floppy_status_names[] = { "ejected", "inserted", NULL }; -int n_floppy_status_names = 2; -char *floppy_bootdisk_names[] = { "floppy", "disk","cdrom", NULL }; -int n_floppy_bootdisk_names = 3; -char *loader_os_names[] = { "none", "linux", "nullkernel", NULL }; -int n_loader_os_names = 3; -char *keyboard_type_names[] = { "xt", "at", "mf", NULL }; -int n_keyboard_type_names = 3; - -char *atadevice_type_names[] = { "disk", "cdrom", NULL }; -int n_atadevice_type_names = 2; -//char *atadevice_mode_names[] = { "flat", "concat", "external", "dll", "sparse", "vmware3", "split", "undoable", "growing", "volatile", "z-undoable", "z-volatile", NULL }; -char *atadevice_mode_names[] = { "flat", "concat", "external", "dll", "sparse", "vmware3", "undoable", "growing", "volatile", NULL }; -int n_atadevice_mode_names = 9; -char *atadevice_status_names[] = { "ejected", "inserted", NULL }; -int n_atadevice_status_names = 2; -char *atadevice_biosdetect_names[] = { "none", "auto", "cmos", NULL }; -int n_atadevice_biosdetect_names = 3; -char *atadevice_translation_names[] = { "none", "lba", "large", "rechs", "auto", NULL }; -int n_atadevice_translation_names = 5; -char *clock_sync_names[] = { "none", "realtime", "slowdown", "both", NULL }; -int clock_sync_n_names=4; - - - -char * -bx_real_sim_c::get_floppy_type_name (int type) -{ - BX_ASSERT (type >= BX_FLOPPY_NONE && type <= BX_FLOPPY_LAST); - type -= BX_FLOPPY_NONE; - return floppy_type_names[type]; -} - -void -bx_real_sim_c::set_notify_callback (bxevent_handler func, void *arg) -{ - bxevent_callback = func; - bxevent_callback_data = arg; -} - -void bx_real_sim_c::get_notify_callback ( - bxevent_handler *func, - void **arg) -{ - *func = bxevent_callback; - *arg = bxevent_callback_data; -} - -BxEvent * -bx_real_sim_c::sim_to_ci_event (BxEvent *event) -{ - if (bxevent_callback == NULL) { - BX_ERROR (("notify called, but no bxevent_callback function is registered")); - return NULL; - } else { - return (*bxevent_callback)(bxevent_callback_data, event); - } -} - -// returns 0 for continue, 1 for alwayscontinue, 2 for die. -int -bx_real_sim_c::log_msg (const char *prefix, int level, const char *msg) -{ - BxEvent be; - be.type = BX_SYNC_EVT_LOG_ASK; - be.u.logmsg.prefix = prefix; - be.u.logmsg.level = level; - be.u.logmsg.msg = msg; - // default return value in case something goes wrong. - be.retcode = BX_LOG_ASK_CHOICE_DIE; - //fprintf (stderr, "calling notify.\n"); - sim_to_ci_event (&be); - return be.retcode; -} - -// Called by simulator whenever it needs the user to choose a new value -// for a registered parameter. Create a synchronous ASK_PARAM event, -// send it to the CI, and wait for the response. The CI will call the -// set() method on the parameter if the user changes the value. -int -bx_real_sim_c::ask_param (bx_id param) -{ - bx_param_c *paramptr = SIM->get_param(param); - BX_ASSERT (paramptr != NULL); - // create appropriate event - BxEvent event; - event.type = BX_SYNC_EVT_ASK_PARAM; - event.u.param.param = paramptr; - sim_to_ci_event (&event); - return event.retcode; -} - -int -bx_real_sim_c::ask_filename (char *filename, int maxlen, char *prompt, char *the_default, int flags) -{ - // implement using ASK_PARAM on a newly created param. I can't use - // ask_param because I don't intend to register this param. - BxEvent event; - bx_param_string_c param (BXP_NULL, prompt, "filename", the_default, maxlen); - flags |= param.IS_FILENAME; - param.get_options()->set (flags); - event.type = BX_SYNC_EVT_ASK_PARAM; - event.u.param.param = ¶m; - sim_to_ci_event (&event); - if (event.retcode >= 0) - memcpy (filename, param.getptr(), maxlen); - return event.retcode; -} - -void -bx_real_sim_c::periodic () -{ - // give the GUI a chance to do periodic things on the bochs thread. in - // particular, notice if the thread has been asked to die. - BxEvent tick; - tick.type = BX_SYNC_EVT_TICK; - sim_to_ci_event (&tick); - if (tick.retcode < 0) { - BX_INFO (("Bochs thread has been asked to quit.")); - bx_atexit (); - quit_sim (0); - } - static int refresh_counter = 0; - if (++refresh_counter == 50) { - // only ask the CI to refresh every 50 times periodic() is called. - // This should obviously be configurable because system speeds and - // user preferences vary. - refresh_ci (); - refresh_counter = 0; - } -#if 0 - // watch for memory leaks. Allocate a small block of memory, print the - // pointer that is returned, then free. - BxEvent *memcheck = new BxEvent (); - BX_INFO(("memory allocation at %p", memcheck)); - delete memcheck; -#endif -} - -// create a disk image file called filename, size=512 bytes * sectors. -// If overwrite is true and the file exists, returns -1 without changing it. -// Otherwise, opens up the image and starts writing. Returns -2 if -// the image could not be opened, or -3 if there are failures during -// write, e.g. disk full. -// -// wxWindows: This may be called from the gui thread. -int -bx_real_sim_c::create_disk_image ( - const char *filename, - int sectors, - bx_bool overwrite) -{ - FILE *fp; - if (!overwrite) { - // check for existence first - fp = fopen (filename, "r"); - if (fp) { - // yes it exists - fclose (fp); - return -1; - } - } - fp = fopen (filename, "w"); - if (fp == NULL) { -#ifdef HAVE_PERROR - char buffer[1024]; - sprintf (buffer, "while opening '%s' for writing", filename); - perror (buffer); - // not sure how to get this back into the CI -#endif - return -2; - } - int sec = sectors; - /* - * seek to sec*512-1 and write a single character. - * can't just do: fseek(fp, 512*sec-1, SEEK_SET) - * because 512*sec may be too large for signed int. - */ - while (sec > 0) - { - /* temp <-- min(sec, 4194303) - * 4194303 is (int)(0x7FFFFFFF/512) - */ - int temp = ((sec < 4194303) ? sec : 4194303); - fseek(fp, 512*temp, SEEK_CUR); - sec -= temp; - } - - fseek(fp, -1, SEEK_CUR); - if (fputc('\0', fp) == EOF) - { - fclose (fp); - return -3; - } - fclose (fp); - return 0; -} - -void bx_real_sim_c::refresh_ci () { - if (SIM->is_wx_selected ()) { - // presently, only wxWindows interface uses these events - // It's an async event, so allocate a pointer and send it. - // The event will be freed by the recipient. - BxEvent *event = new BxEvent (); - event->type = BX_ASYNC_EVT_REFRESH; - sim_to_ci_event (event); - } -} - -bx_param_c * -bx_real_sim_c::get_first_atadevice (Bit32u search_type) { - for (int channel=0; channelget ()) - continue; - for (int slave=0; slave<2; slave++) { - Bit32u present = bx_options.atadevice[channel][slave].Opresent->get (); - Bit32u type = bx_options.atadevice[channel][slave].Otype->get (); - if (present && (type == search_type)) { - return bx_options.atadevice[channel][slave].Omenu; - } - } - } - return NULL; -} - -#if BX_DEBUGGER - -// this can be safely called from either thread. -void bx_real_sim_c::debug_break () { - bx_debug_break (); -} - -// this should only be called from the sim_thread. -void bx_real_sim_c::debug_interpret_cmd (char *cmd) { - if (!is_sim_thread ()) { - fprintf (stderr, "ERROR: debug_interpret_cmd called but not from sim_thread\n"); - return; - } - bx_dbg_interpret_line (cmd); -} - -char *bx_real_sim_c::debug_get_next_command () -{ - fprintf (stderr, "begin debug_get_next_command\n"); - BxEvent event; - event.type = BX_SYNC_EVT_GET_DBG_COMMAND; - BX_INFO (("asking for next debug command")); - sim_to_ci_event (&event); - BX_INFO (("received next debug command: '%s'", event.u.debugcmd.command)); - if (event.retcode >= 0) - return event.u.debugcmd.command; - return NULL; -} - -void bx_real_sim_c::debug_puts (const char *text) -{ - if (SIM->is_wx_selected ()) { - // send message to the wxWindows debugger - BxEvent *event = new BxEvent (); - event->type = BX_ASYNC_EVT_DBG_MSG; - event->u.logmsg.msg = text; - sim_to_ci_event (event); - // the event will be freed by the recipient - } else { - // text mode debugger: just write to console - fputs (text, stderr); - delete [] (char *)text; - } -} -#endif - -void -bx_real_sim_c::register_configuration_interface ( - const char* name, - config_interface_callback_t callback, - void *userdata) -{ - ci_callback = callback; - ci_callback_data = userdata; - registered_ci_name = name; -} - -int -bx_real_sim_c::configuration_interface(const char *ignore, ci_command_t command) -{ - bx_param_enum_c *ci_param = SIM->get_param_enum (BXP_SEL_CONFIG_INTERFACE); - char *name = ci_param->get_choice (ci_param->get ()); - if (!ci_callback) { - BX_PANIC (("no configuration interface was loaded")); - return -1; - } - if (strcmp (name, registered_ci_name) != 0) { - BX_PANIC (("siminterface does not support loading one configuration interface and then calling another")); - return -1; - } - if (!strcmp (name, "wx")) - wxsel = true; - else - wxsel = false; - // enter configuration mode, just while running the configuration interface - set_display_mode (DISP_MODE_CONFIG); - int retval = (*ci_callback)(ci_callback_data, command); - set_display_mode (DISP_MODE_SIM); - return retval; -} - -int -bx_real_sim_c::begin_simulation (int argc, char *argv[]) -{ - return bx_begin_simulation (argc, argv); -} - -bool bx_real_sim_c::is_sim_thread () -{ - if (is_sim_thread_func == NULL) return true; - return (*is_sim_thread_func)(); -} - -// check if the text console exists. On some platforms, if Bochs is -// started from the "Start Menu" or by double clicking on it on a Mac, -// there may be nothing attached to stdin/stdout/stderr. This function -// tests if stdin/stdout/stderr are usable and returns false if not. -bool -bx_real_sim_c::test_for_text_console () -{ -#if BX_WITH_CARBON - // In a Carbon application, you have a text console if you run the app from - // the command line, but if you start it from the finder you don't. - if(!isatty(STDIN_FILENO)) return false; -#endif - // default: yes - return true; -} - - -///////////////////////////////////////////////////////////////////////// -// define methods of bx_param_* and family -///////////////////////////////////////////////////////////////////////// - -bx_object_c::bx_object_c (bx_id id) -{ - this->id = id; - this->type = BXT_OBJECT; -} - -void -bx_object_c::set_type (bx_objtype type) -{ - this->type = type; -} - -const char* bx_param_c::default_text_format = NULL; - -bx_param_c::bx_param_c (bx_id id, char *name, char *description) - : bx_object_c (id) -{ - set_type (BXT_PARAM); - this->name = name; - this->description = description; - this->text_format = default_text_format; - this->ask_format = NULL; - this->label = NULL; - this->runtime_param = 0; - this->enabled = 1; - SIM->register_param (id, this); -} - -const char* bx_param_c::set_default_format (const char *f) { - const char *old = default_text_format; - default_text_format = f; - return old; -} - -bx_param_num_c::bx_param_num_c (bx_id id, - char *name, - char *description, - Bit64s min, Bit64s max, Bit64s initial_val) - : bx_param_c (id, name, description) -{ - set_type (BXT_PARAM_NUM); - this->min = min; - this->max = max; - this->initial_val = initial_val; - this->val.number = initial_val; - this->handler = NULL; - this->enable_handler = NULL; - this->base = default_base; - // dependent_list must be initialized before the set(), - // because set calls update_dependents(). - dependent_list = NULL; - set (initial_val); -} - -Bit32u bx_param_num_c::default_base = 10; - -Bit32u bx_param_num_c::set_default_base (Bit32u val) { - Bit32u old = default_base; - default_base = val; - return old; -} - -void -bx_param_num_c::reset () -{ - this->val.number = initial_val; -} - -void -bx_param_num_c::set_handler (param_event_handler handler) -{ - this->handler = handler; - // now that there's a handler, call set once to run the handler immediately - //set (get ()); -} - -void -bx_param_num_c::set_enable_handler (param_enable_handler handler) -{ - this->enable_handler = handler; -} - -void bx_param_num_c::set_dependent_list (bx_list_c *l) { - dependent_list = l; - update_dependents (); -} - -Bit64s -bx_param_num_c::get64 () -{ - if (handler) { - // the handler can decide what value to return and/or do some side effect - return (*handler)(this, 0, val.number); - } else { - // just return the value - return val.number; - } -} - -void -bx_param_num_c::set (Bit64s newval) -{ - if (handler) { - // the handler can override the new value and/or perform some side effect - val.number = newval; - (*handler)(this, 1, newval); - } else { - // just set the value. This code does not check max/min. - val.number = newval; - } - if ((val.number < min || val.number > max) && (Bit64u)max != BX_MAX_BIT64U) - BX_PANIC (("numerical parameter %s was set to " FMT_LL "d, which is out of range " FMT_LL "d to " FMT_LL "d", get_name (), val.number, min, max)); - if (dependent_list != NULL) update_dependents (); -} - -void bx_param_num_c::set_range (Bit64u min, Bit64u max) -{ - this->min = min; - this->max = max; -} - -void bx_param_num_c::set_initial_val (Bit64s initial_val) { - this->val.number = this->initial_val = initial_val; -} - -void bx_param_num_c::update_dependents () -{ - if (dependent_list) { - int en = val.number && enabled; - for (int i=0; iget_size (); i++) { - bx_param_c *param = dependent_list->get (i); - if (param != this) - param->set_enabled (en); - } - } -} - -void -bx_param_num_c::set_enabled (int en) -{ - // The enable handler may wish to allow/disallow the action - if (enable_handler) { - en = (*enable_handler) (this, en); - } - bx_param_c::set_enabled (en); - update_dependents (); -} - -// Signed 64 bit -bx_shadow_num_c::bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit64s *ptr_to_real_val, - Bit8u highbit, - Bit8u lowbit) -: bx_param_num_c (id, name, description, BX_MIN_BIT64S, BX_MAX_BIT64S, *ptr_to_real_val) -{ - this->varsize = 16; - this->lowbit = lowbit; - this->mask = (1 << (highbit - lowbit)) - 1; - val.p64bit = ptr_to_real_val; -} - -// Unsigned 64 bit -bx_shadow_num_c::bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit64u *ptr_to_real_val, - Bit8u highbit, - Bit8u lowbit) -: bx_param_num_c (id, name, description, BX_MIN_BIT64U, BX_MAX_BIT64U, *ptr_to_real_val) -{ - this->varsize = 16; - this->lowbit = lowbit; - this->mask = (1 << (highbit - lowbit)) - 1; - val.p64bit = (Bit64s*) ptr_to_real_val; -} - -// Signed 32 bit -bx_shadow_num_c::bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit32s *ptr_to_real_val, - Bit8u highbit, - Bit8u lowbit) -: bx_param_num_c (id, name, description, BX_MIN_BIT32S, BX_MAX_BIT32S, *ptr_to_real_val) -{ - this->varsize = 16; - this->lowbit = lowbit; - this->mask = (1 << (highbit - lowbit)) - 1; - val.p32bit = ptr_to_real_val; -} - -// Unsigned 32 bit -bx_shadow_num_c::bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit32u *ptr_to_real_val, - Bit8u highbit, - Bit8u lowbit) -: bx_param_num_c (id, name, description, BX_MIN_BIT32U, BX_MAX_BIT32U, *ptr_to_real_val) -{ - this->varsize = 32; - this->lowbit = lowbit; - this->mask = (1 << (highbit - lowbit)) - 1; - val.p32bit = (Bit32s*) ptr_to_real_val; -} - -// Signed 16 bit -bx_shadow_num_c::bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit16s *ptr_to_real_val, - Bit8u highbit, - Bit8u lowbit) -: bx_param_num_c (id, name, description, BX_MIN_BIT16S, BX_MAX_BIT16S, *ptr_to_real_val) -{ - this->varsize = 16; - this->lowbit = lowbit; - this->mask = (1 << (highbit - lowbit)) - 1; - val.p16bit = ptr_to_real_val; -} - -// Unsigned 16 bit -bx_shadow_num_c::bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit16u *ptr_to_real_val, - Bit8u highbit, - Bit8u lowbit) -: bx_param_num_c (id, name, description, BX_MIN_BIT16U, BX_MAX_BIT16U, *ptr_to_real_val) -{ - this->varsize = 16; - this->lowbit = lowbit; - this->mask = (1 << (highbit - lowbit)) - 1; - val.p16bit = (Bit16s*) ptr_to_real_val; -} - -// Signed 8 bit -bx_shadow_num_c::bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit8s *ptr_to_real_val, - Bit8u highbit, - Bit8u lowbit) -: bx_param_num_c (id, name, description, BX_MIN_BIT8S, BX_MAX_BIT8S, *ptr_to_real_val) -{ - this->varsize = 16; - this->lowbit = lowbit; - this->mask = (1 << (highbit - lowbit)) - 1; - val.p8bit = ptr_to_real_val; -} - -// Unsigned 8 bit -bx_shadow_num_c::bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit8u *ptr_to_real_val, - Bit8u highbit, - Bit8u lowbit) -: bx_param_num_c (id, name, description, BX_MIN_BIT8U, BX_MAX_BIT8U, *ptr_to_real_val) -{ - this->varsize = 8; - this->lowbit = lowbit; - this->mask = (1 << (highbit - lowbit)) - 1; - val.p8bit = (Bit8s*) ptr_to_real_val; -} - -Bit64s -bx_shadow_num_c::get64 () { - Bit64u current = 0; - switch (varsize) { - case 8: current = *(val.p8bit); break; - case 16: current = *(val.p16bit); break; - case 32: current = *(val.p32bit); break; - case 64: current = *(val.p64bit); break; - default: BX_PANIC(("unsupported varsize %d", varsize)); - } - current = (current >> lowbit) & mask; - if (handler) { - // the handler can decide what value to return and/or do some side effect - return (*handler)(this, 0, current) & mask; - } else { - // just return the value - return current; - } -} - -void -bx_shadow_num_c::set (Bit64s newval) -{ - Bit64u tmp = 0; - if ((newval < min || newval > max) && (Bit64u)max != BX_MAX_BIT64U) - BX_PANIC (("numerical parameter %s was set to " FMT_LL "d, which is out of range " FMT_LL "d to " FMT_LL "d", get_name (), newval, min, max)); - switch (varsize) { - case 8: - tmp = (*(val.p8bit) >> lowbit) & mask; - tmp |= (newval & mask) << lowbit; - *(val.p8bit) = (Bit8s)tmp; - break; - case 16: - tmp = (*(val.p16bit) >> lowbit) & mask; - tmp |= (newval & mask) << lowbit; - *(val.p16bit) = (Bit16s)tmp; - break; - case 32: - tmp = (*(val.p32bit) >> lowbit) & mask; - tmp |= (newval & mask) << lowbit; - *(val.p32bit) = (Bit32s)tmp; - break; - case 64: - tmp = (*(val.p64bit) >> lowbit) & mask; - tmp |= (newval & mask) << lowbit; - *(val.p64bit) = tmp; - break; - default: - BX_PANIC(("unsupported varsize %d", varsize)); - } - if (handler) { - // the handler can override the new value and/or perform some side effect - (*handler)(this, 1, tmp); - } -} - -bx_param_bool_c::bx_param_bool_c (bx_id id, - char *name, - char *description, - Bit64s initial_val) - : bx_param_num_c (id, name, description, 0, 1, initial_val) -{ - set_type (BXT_PARAM_BOOL); - set (initial_val); -} - -bx_shadow_bool_c::bx_shadow_bool_c (bx_id id, - char *name, - char *description, - bx_bool *ptr_to_real_val, - Bit8u bitnum) - : bx_param_bool_c (id, name, description, (Bit64s) *ptr_to_real_val) -{ - val.pbool = ptr_to_real_val; - this->bitnum = bitnum; -} - -Bit64s -bx_shadow_bool_c::get64 () { - if (handler) { - // the handler can decide what value to return and/or do some side effect - Bit64s ret = (*handler)(this, 0, (Bit64s) *(val.pbool)); - return (ret>>bitnum) & 1; - } else { - // just return the value - return (*(val.pbool)) & 1; - } -} - -void -bx_shadow_bool_c::set (Bit64s newval) -{ - // only change the bitnum bit - Bit64s tmp = (newval&1) << bitnum; - *(val.pbool) &= ~tmp; - *(val.pbool) |= tmp; - if (handler) { - // the handler can override the new value and/or perform some side effect - (*handler)(this, 1, newval&1); - } -} - -bx_param_enum_c::bx_param_enum_c (bx_id id, - char *name, - char *description, - char **choices, - Bit64s initial_val, - Bit64s value_base) - : bx_param_num_c (id, name, description, value_base, BX_MAX_BIT64S, initial_val) -{ - set_type (BXT_PARAM_ENUM); - this->choices = choices; - // count number of choices, set max - char **p = choices; - while (*p != NULL) p++; - this->min = value_base; - // now that the max is known, replace the BX_MAX_BIT64S sent to the parent - // class constructor with the real max. - this->max = value_base + (p - choices - 1); - set (initial_val); -} - -int -bx_param_enum_c::find_by_name (const char *string) -{ - char **p; - for (p=&choices[0]; *p; p++) { - if (!strcmp (string, *p)) - return p-choices; - } - return -1; -} - -bool -bx_param_enum_c::set_by_name (const char *string) -{ - int n = find_by_name (string); - if (n<0) return false; - set (n); - return true; -} - -bx_param_string_c::bx_param_string_c (bx_id id, - char *name, - char *description, - char *initial_val, - int maxsize) - : bx_param_c (id, name, description) -{ - set_type (BXT_PARAM_STRING); - if (maxsize < 0) - maxsize = strlen(initial_val) + 1; - this->val = new char[maxsize]; - this->initial_val = new char[maxsize]; - this->handler = NULL; - this->enable_handler = NULL; - this->maxsize = maxsize; - strncpy (this->val, initial_val, maxsize); - strncpy (this->initial_val, initial_val, maxsize); - this->options = new bx_param_num_c (BXP_NULL, - "stringoptions", NULL, 0, BX_MAX_BIT64S, 0); - set (initial_val); -} - -bx_param_filename_c::bx_param_filename_c (bx_id id, - char *name, - char *description, - char *initial_val, - int maxsize) - : bx_param_string_c (id, name, description, initial_val, maxsize) -{ - get_options()->set (IS_FILENAME); -} - -bx_param_string_c::~bx_param_string_c () -{ - if ( this->val != NULL ) - { - delete [] this->val; - this->val = NULL; - } - if ( this->initial_val != NULL ) - { - delete [] this->initial_val; - this->initial_val = NULL; - } - - if ( this->options != NULL ) - { - delete [] this->options; - this->options = NULL; - } -} - -void -bx_param_string_c::reset () { - strncpy (this->val, this->initial_val, maxsize); -} - -void -bx_param_string_c::set_handler (param_string_event_handler handler) -{ - this->handler = handler; - // now that there's a handler, call set once to run the handler immediately - //set (getptr ()); -} - -void -bx_param_string_c::set_enable_handler (param_enable_handler handler) -{ - this->enable_handler = handler; -} - -void -bx_param_string_c::set_enabled (int en) -{ - // The enable handler may wish to allow/disallow the action - if (enable_handler) { - en = (*enable_handler) (this, en); - } - bx_param_c::set_enabled (en); -} - -Bit32s -bx_param_string_c::get (char *buf, int len) -{ - if (options->get () & RAW_BYTES) - memcpy (buf, val, len); - else - strncpy (buf, val, len); - if (handler) { - // the handler can choose to replace the value in val/len. Also its - // return value is passed back as the return value of get. - (*handler)(this, 0, buf, len); - } - return 0; -} - -void -bx_param_string_c::set (char *buf) -{ - if (options->get () & RAW_BYTES) - memcpy (val, buf, maxsize); - else - strncpy (val, buf, maxsize); - if (handler) { - // the handler can return a different char* to be copied into the value - buf = (*handler)(this, 1, buf, -1); - } -} - -bx_bool -bx_param_string_c::equals (const char *buf) -{ - if (options->get () & RAW_BYTES) - return (memcmp (val, buf, maxsize) == 0); - else - return (strncmp (val, buf, maxsize) == 0); -} - -bx_list_c::bx_list_c (bx_id id, int maxsize) - : bx_param_c (id, "list", "") -{ - set_type (BXT_LIST); - this->size = 0; - this->maxsize = maxsize; - this->list = new bx_param_c* [maxsize]; - init (); -} - -bx_list_c::bx_list_c (bx_id id, char *name, char *description, int maxsize) - : bx_param_c (id, name, description) -{ - set_type (BXT_LIST); - this->size = 0; - this->maxsize = maxsize; - this->list = new bx_param_c* [maxsize]; - init (); -} - -bx_list_c::bx_list_c (bx_id id, char *name, char *description, bx_param_c **init_list) - : bx_param_c (id, name, description) -{ - set_type (BXT_LIST); - this->size = 0; - while (init_list[this->size] != NULL) - this->size++; - this->maxsize = this->size; - this->list = new bx_param_c* [maxsize]; - for (int i=0; isize; i++) - this->list[i] = init_list[i]; - init (); -} - -bx_list_c::~bx_list_c() -{ - if (this->list) - { - delete [] this->list; - this->list = NULL; - } - if ( this->title != NULL) - { - delete this->title; - this->title = NULL; - } - if (this->options != NULL) - { - delete this->options; - this->options = NULL; - } - if ( this->choice != NULL ) - { - delete this->choice; - this->choice = NULL; - } -} - -void -bx_list_c::init () -{ - // the title defaults to the name - this->title = new bx_param_string_c (BXP_NULL, - "title of list", - "", - get_name (), 80); - this->options = new bx_param_num_c (BXP_NULL, - "list_option", "", 0, BX_MAX_BIT64S, - 0); - this->choice = new bx_param_num_c (BXP_NULL, - "list_choice", "", 0, BX_MAX_BIT64S, - 1); - this->parent = NULL; -} - -bx_list_c * -bx_list_c::clone () -{ - bx_list_c *newlist = new bx_list_c (BXP_NULL, name, description, maxsize); - for (int i=0; iadd (get(i)); - newlist->set_options (get_options ()); - newlist->set_parent (get_parent ()); - return newlist; -} - -void -bx_list_c::add (bx_param_c *param) -{ - if (this->size >= this->maxsize) - BX_PANIC (("add param %u to bx_list_c id=%u: list capacity exceeded", param->get_id (), get_id ())); - list[size] = param; - size++; -} - -bx_param_c * -bx_list_c::get (int index) -{ - BX_ASSERT (index >= 0 && index < size); - return list[index]; -} - diff --git a/tools/ioemu/gui/siminterface.h b/tools/ioemu/gui/siminterface.h deleted file mode 100644 index 9a028470c8..0000000000 --- a/tools/ioemu/gui/siminterface.h +++ /dev/null @@ -1,1460 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: siminterface.h,v 1.113.2.2 2004/02/06 22:14:35 danielg4 Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Before I can describe what this file is for, I have to make the -// distinction between a configuration interface (CI) and the VGA display -// window (VGAW). I will try to avoid the term 'GUI' because it is unclear -// if that means CI or VGAW, and because not all interfaces are graphical -// anyway. -// -// The traditional Bochs screen is a window with a large VGA display panel and -// a series of buttons (floppy, cdrom, snapshot, power). Over the years, we -// have collected many implementations of the VGAW for different environments -// and platforms; each implementation is in a separate file under gui/*: -// x.cc, win32.cc, beos.cc, macintosh.cc, etc. The files gui.h and gui.cc -// define the platform independent part of the VGAW, leaving about 15 methods -// of the bx_gui_c class undefined. The platform dependent file must -// implement the remaining 15 methods. -// -// The configuration interface is relatively new, started by Bryce Denney in -// June 2001. The CI is intended to allow the user to edit a variety of -// configuration and runtime options. Some options, such as memory size or -// enabling the ethernet card, should only be changed before the simulation -// begins; others, such as floppy disk image, instructions per second, and -// logging options can be safely changed at runtime. The CI allows the user to -// make these changes. Before the CI existed, only a few things could be -// changed at runtime, all linked to clicking on the VGAW buttons. -// -// At the time that the CI was conceived, we were still debating what form the -// user interface part would take: stdin/stdout menus, a graphical application -// with menus and dialogs running in a separate thread, or even a tiny web -// server that you can connect to with a web browser. As a result the -// interface to the CI was designed so that the user interface of the CI -// could be replaced easily at compile time, or maybe even at runtime via -// a plugin architecture. To this end, we kept a clear separation between -// the user interface code and the siminterface, the code that interfaces with -// the simulator. The same siminterface is used all the time, while -// different implementations of the CI can be switched in reasonably easily. -// Only the CI code uses library specific graphics and I/O functions; the -// siminterface deals in portable abstractions and callback functions. -// The first CI implementation was a series of text mode menus implemented in -// control.cc. -// -// The configuration interface MUST use the siminterface methods to access the -// simulator. It should not modify settings in some device with code like -// bx_floppy.s.media[2].heads = 17. If such access is needed, then a -// siminterface method should be written to make the change on the CI's behalf. -// This separation is enforced by the fact that the CI does not even include -// bochs.h. You'll notice that control.cc include osdep.h, control.h, and -// siminterface.h, so it doesn't know what bx_floppy or bx_cpu_c are. I'm sure -// some people will say is overly restrictive and/or annoying. When I set it -// up this way, we were still talking about making the CI in a seperate -// process, where direct method calls would be impossible. Also, we have been -// considering turning devices into plugin modules which are dynamically -// linked. Any direct references to something like bx_floppy.s.media[2].heads -// would have to be reworked before a plugin interface was possible as well. -// -// The siminterface is the glue between the CI and the simulator. There is -// just one global instance of the siminterface object, which can be referred -// to by the global variable bx_simulator_interface_c *SIM; The base class -// bx_simulator_interface_c, contains only virtual functions and it defines the -// interface that the CI is allowed to use. In siminterface.cc, a class -// called bx_real_sim_c is defined with bx_simulator_interface_c as its parent -// class. Bx_real_sim_c implements each of the functions. The separation into -// parent class and child class leaves the possibility of making a different -// child class that talks to the simulator in a different way (networking for -// example). If you were writing a user interface in a separate process, you -// could define a subclass of bx_simulator_interface_c called -// bx_siminterface_proxy_c which opens up a network port and turns all method -// calls into network sends and receives. Because the interface is defined -// entirely by the base class, the code that calls the methods would not know -// the difference. -// -// An important part of the siminterface implementation is the use of parameter -// classes, or bx_param_*. The parameter classes are described below, where -// they are declared. Search for "parameter classes" below for detals. -// -// Also this header file declares data structures for certain events that pass -// between the siminterface and the CI. Search for "event structures" below. - - - -////////////////////////////////////////////////////// -// BX_UI_TEXT should be set to 1 when the text mode configuration interface -// is compiled in. This gives each type of parameter a text_print and text_ask -// method (defined in gui/control.cc) so that you can call text_ask() on any -// kind of parameter to ask the user to edit the value. -// -// I have been considering whether to use the same strategy for the -// wxWindows interface, but I'm not sure if I like it. One problem is -// that in order to declare member functions that are useful for -// wxWindows, the wxWindows header files would have to be included -// before the param object definitions. That means that all the -// wxwindows headers would have be included when compiling every -// single bochs file. One of the things I like about the separation -// between the simulator and CI is that the two parts can be -// compiled without any knowledge of the other. Bochs doesn't include -// , and the wxwindows CI (wxmain.cc) doesn't need to include . -// Aside from making compiles faster, this enforces the use of the siminterface -// so it keeps the interface clean (important when we may have multiple UI -// implementations for example). This argues for keeping UI-specific -// structures out of the simulator interface. It certainly works ok for the -// text interface, but that's because FILE* is standard and portable. -#define BX_UI_TEXT 1 - -////////////////////////////////////////////////////// - -// list of possible types for bx_param_c and descendant objects -typedef enum { - BXT_OBJECT = 201, - BXT_PARAM, - BXT_PARAM_NUM, - BXT_PARAM_BOOL, - BXT_PARAM_ENUM, - BXT_PARAM_STRING, - BXT_LIST -} bx_objtype; - -// list if parameter id values. The actual values are not important; -// it's only important that they all be different from each other. -typedef enum { - BXP_NULL = 301, - BXP_IPS, - BXP_REALTIME_PIT, - BXP_TEXT_SNAPSHOT_CHECK, - BXP_VGA_UPDATE_INTERVAL, - BXP_MOUSE_ENABLED, - BXP_MEM_SIZE, - BXP_ROM_PATH, - BXP_ROM_ADDRESS, - BXP_VGA_ROM_PATH, - BXP_OPTROM1_PATH, - BXP_OPTROM2_PATH, - BXP_OPTROM3_PATH, - BXP_OPTROM4_PATH, - BXP_OPTROM1_ADDRESS, - BXP_OPTROM2_ADDRESS, - BXP_OPTROM3_ADDRESS, - BXP_OPTROM4_ADDRESS, - BXP_KBD_SERIAL_DELAY, - BXP_KBD_PASTE_DELAY, - BXP_KBD_TYPE, - BXP_FLOPPY_CMD_DELAY, - BXP_FLOPPYA_DEVTYPE, - BXP_FLOPPYA_PATH, - BXP_FLOPPYA_TYPE, - BXP_FLOPPYA_STATUS, - BXP_FLOPPYA, - BXP_FLOPPYB_DEVTYPE, - BXP_FLOPPYB_PATH, - BXP_FLOPPYB_TYPE, - BXP_FLOPPYB_STATUS, - BXP_FLOPPYB, - - BXP_ATA0_MENU, - BXP_ATA1_MENU, - BXP_ATA2_MENU, - BXP_ATA3_MENU, -#define BXP_ATAx_MENU(i) (BXP_ATA0_MENU + (i)) - BXP_ATA0, - BXP_ATA1, - BXP_ATA2, - BXP_ATA3, -#define BXP_ATAx(i) (BXP_ATA0 + (i)) - BXP_ATA0_PRESENT, - BXP_ATA1_PRESENT, - BXP_ATA2_PRESENT, - BXP_ATA3_PRESENT, -#define BXP_ATAx_PRESENT(i) (BXP_ATA0_PRESENT + (i)) - BXP_ATA0_IOADDR1, - BXP_ATA1_IOADDR1, - BXP_ATA2_IOADDR1, - BXP_ATA3_IOADDR1, -#define BXP_ATAx_IOADDR1(i) (BXP_ATA0_IOADDR1 + (i)) - BXP_ATA0_IOADDR2, - BXP_ATA1_IOADDR2, - BXP_ATA2_IOADDR2, - BXP_ATA3_IOADDR2, -#define BXP_ATAx_IOADDR2(i) (BXP_ATA0_IOADDR2 + (i)) - BXP_ATA0_IRQ, - BXP_ATA1_IRQ, - BXP_ATA2_IRQ, - BXP_ATA3_IRQ, -#define BXP_ATAx_IRQ(i) (BXP_ATA0_IRQ + (i)) - - BXP_ATA0_MASTER, - BXP_ATA0_SLAVE, - BXP_ATA1_MASTER, - BXP_ATA1_SLAVE, - BXP_ATA2_MASTER, - BXP_ATA2_SLAVE, - BXP_ATA3_MASTER, - BXP_ATA3_SLAVE, -#define BXP_ATAx_DEVICE(i, s) (BXP_ATA0_MASTER + (2*(i)) + (s)) - -#define BXP_PARAMS_PER_ATA_DEVICE 12 - - BXP_ATA0_MASTER_PRESENT, - BXP_ATA0_SLAVE_PRESENT, - BXP_ATA1_MASTER_PRESENT, - BXP_ATA1_SLAVE_PRESENT, - BXP_ATA2_MASTER_PRESENT, - BXP_ATA2_SLAVE_PRESENT, - BXP_ATA3_MASTER_PRESENT, - BXP_ATA3_SLAVE_PRESENT, -#define BXP_ATAx_DEVICE_PRESENT(i, s) (BXP_ATA0_MASTER_PRESENT + (2*(i)) + (s)) - - BXP_ATA0_MASTER_TYPE, - BXP_ATA0_SLAVE_TYPE, - BXP_ATA1_MASTER_TYPE, - BXP_ATA1_SLAVE_TYPE, - BXP_ATA2_MASTER_TYPE, - BXP_ATA2_SLAVE_TYPE, - BXP_ATA3_MASTER_TYPE, - BXP_ATA3_SLAVE_TYPE, -#define BXP_ATAx_DEVICE_TYPE(i, s) (BXP_ATA0_MASTER_TYPE + (2*(i)) + (s)) - - BXP_ATA0_MASTER_MODE, - BXP_ATA0_SLAVE_MODE, - BXP_ATA1_MASTER_MODE, - BXP_ATA1_SLAVE_MODE, - BXP_ATA2_MASTER_MODE, - BXP_ATA2_SLAVE_MODE, - BXP_ATA3_MASTER_MODE, - BXP_ATA3_SLAVE_MODE, -#define BXP_ATAx_DEVICE_MODE(i, s) (BXP_ATA0_MASTER_MODE + (2*(i)) + (s)) - - BXP_ATA0_MASTER_PATH, - BXP_ATA0_SLAVE_PATH, - BXP_ATA1_MASTER_PATH, - BXP_ATA1_SLAVE_PATH, - BXP_ATA2_MASTER_PATH, - BXP_ATA2_SLAVE_PATH, - BXP_ATA3_MASTER_PATH, - BXP_ATA3_SLAVE_PATH, -#define BXP_ATAx_DEVICE_PATH(i, s) (BXP_ATA0_MASTER_PATH + (2*(i)) + (s)) - - BXP_ATA0_MASTER_CYLINDERS, - BXP_ATA0_SLAVE_CYLINDERS, - BXP_ATA1_MASTER_CYLINDERS, - BXP_ATA1_SLAVE_CYLINDERS, - BXP_ATA2_MASTER_CYLINDERS, - BXP_ATA2_SLAVE_CYLINDERS, - BXP_ATA3_MASTER_CYLINDERS, - BXP_ATA3_SLAVE_CYLINDERS, -#define BXP_ATAx_DEVICE_CYLINDERS(i, s) (BXP_ATA0_MASTER_CYLINDERS + (2*(i)) + (s)) - - BXP_ATA0_MASTER_HEADS, - BXP_ATA0_SLAVE_HEADS, - BXP_ATA1_MASTER_HEADS, - BXP_ATA1_SLAVE_HEADS, - BXP_ATA2_MASTER_HEADS, - BXP_ATA2_SLAVE_HEADS, - BXP_ATA3_MASTER_HEADS, - BXP_ATA3_SLAVE_HEADS, -#define BXP_ATAx_DEVICE_HEADS(i, s) (BXP_ATA0_MASTER_HEADS + (2*(i)) + (s)) - - BXP_ATA0_MASTER_SPT, - BXP_ATA0_SLAVE_SPT, - BXP_ATA1_MASTER_SPT, - BXP_ATA1_SLAVE_SPT, - BXP_ATA2_MASTER_SPT, - BXP_ATA2_SLAVE_SPT, - BXP_ATA3_MASTER_SPT, - BXP_ATA3_SLAVE_SPT, -#define BXP_ATAx_DEVICE_SPT(i, s) (BXP_ATA0_MASTER_SPT + (2*(i)) + (s)) - - BXP_ATA0_MASTER_STATUS, - BXP_ATA0_SLAVE_STATUS, - BXP_ATA1_MASTER_STATUS, - BXP_ATA1_SLAVE_STATUS, - BXP_ATA2_MASTER_STATUS, - BXP_ATA2_SLAVE_STATUS, - BXP_ATA3_MASTER_STATUS, - BXP_ATA3_SLAVE_STATUS, -#define BXP_ATAx_DEVICE_STATUS(i, s) (BXP_ATA0_MASTER_STATUS + (2*(i)) + (s)) - - BXP_ATA0_MASTER_MODEL, - BXP_ATA0_SLAVE_MODEL, - BXP_ATA1_MASTER_MODEL, - BXP_ATA1_SLAVE_MODEL, - BXP_ATA2_MASTER_MODEL, - BXP_ATA2_SLAVE_MODEL, - BXP_ATA3_MASTER_MODEL, - BXP_ATA3_SLAVE_MODEL, -#define BXP_ATAx_DEVICE_MODEL(i, s) (BXP_ATA0_MASTER_MODEL + (2*(i)) + (s)) - - BXP_ATA0_MASTER_BIOSDETECT, - BXP_ATA0_SLAVE_BIOSDETECT, - BXP_ATA1_MASTER_BIOSDETECT, - BXP_ATA1_SLAVE_BIOSDETECT, - BXP_ATA2_MASTER_BIOSDETECT, - BXP_ATA2_SLAVE_BIOSDETECT, - BXP_ATA3_MASTER_BIOSDETECT, - BXP_ATA3_SLAVE_BIOSDETECT, -#define BXP_ATAx_DEVICE_BIOSDETECT(i, s) (BXP_ATA0_MASTER_BIOSDETECT + (2*(i)) + (s)) - - BXP_ATA0_MASTER_TRANSLATION, - BXP_ATA0_SLAVE_TRANSLATION, - BXP_ATA1_MASTER_TRANSLATION, - BXP_ATA1_SLAVE_TRANSLATION, - BXP_ATA2_MASTER_TRANSLATION, - BXP_ATA2_SLAVE_TRANSLATION, - BXP_ATA3_MASTER_TRANSLATION, - BXP_ATA3_SLAVE_TRANSLATION, -#define BXP_ATAx_DEVICE_TRANSLATION(i, s) (BXP_ATA0_MASTER_TRANSLATION + (2*(i)) + (s)) - - BXP_ATA0_MASTER_JOURNAL, - BXP_ATA0_SLAVE_JOURNAL, - BXP_ATA1_MASTER_JOURNAL, - BXP_ATA1_SLAVE_JOURNAL, - BXP_ATA2_MASTER_JOURNAL, - BXP_ATA2_SLAVE_JOURNAL, - BXP_ATA3_MASTER_JOURNAL, - BXP_ATA3_SLAVE_JOURNAL, -#define BXP_ATAx_DEVICE_JOURNAL(i, s) (BXP_ATA0_MASTER_JOURNAL + (2*(i)) + (s)) - -#define BXP_PARAMS_PER_SERIAL_PORT 2 - BXP_COM1_ENABLED, - BXP_COM1_PATH, - BXP_COM2_ENABLED, - BXP_COM2_PATH, - BXP_COM3_ENABLED, - BXP_COM3_PATH, - BXP_COM4_ENABLED, - BXP_COM4_PATH, -#define BXP_PARAMS_PER_USB_HUB 3 - BXP_USB1_ENABLED, - BXP_USB1_IOADDR, - BXP_USB1_IRQ, - BXP_PRIVATE_COLORMAP, - BXP_FULLSCREEN, - BXP_SCREENMODE, - BXP_I440FX_SUPPORT, - BXP_NEWHARDDRIVESUPPORT, - BXP_LOG_FILENAME, - BXP_LOG_PREFIX, - BXP_DEBUGGER_LOG_FILENAME, - BXP_CMOS_PATH, - BXP_CMOS_IMAGE, - BXP_CLOCK, - BXP_CLOCK_TIME0, - BXP_CLOCK_SYNC, - BXP_LOAD32BITOS_WHICH, - BXP_LOAD32BITOS_PATH, - BXP_LOAD32BITOS_IOLOG, - BXP_LOAD32BITOS_INITRD, - BXP_LOAD32BITOS, - BXP_BOOTDRIVE, - BXP_FLOPPYSIGCHECK, - BXP_MENU_MAIN, - BXP_MENU_MEMORY, - BXP_MENU_INTERFACE, - BXP_MENU_DISK, - BXP_MENU_SERIAL_PARALLEL, - BXP_MENU_SOUND, - BXP_MENU_KEYBOARD, - BXP_MENU_MISC, - BXP_MENU_MISC_2, - BXP_MENU_RUNTIME, - BXP_MAX_IPS, - BXP_NE2K_PRESENT, - BXP_NE2K_IOADDR, - BXP_NE2K_IRQ, - BXP_NE2K_MACADDR, - BXP_NE2K_ETHMOD, - BXP_NE2K_ETHDEV, - BXP_NE2K_SCRIPT, - BXP_NE2K, - BXP_SB16_PRESENT, - BXP_SB16_MIDIFILE, - BXP_SB16_WAVEFILE, - BXP_SB16_LOGFILE, - BXP_SB16_MIDIMODE, - BXP_SB16_WAVEMODE, - BXP_SB16_LOGLEVEL, - BXP_SB16_DMATIMER, - BXP_SB16, -#define BXP_PARAMS_PER_PARALLEL_PORT 2 - BXP_PARPORT1_ENABLED, - BXP_PARPORT1_OUTFILE, - BXP_PARPORT2_ENABLED, - BXP_PARPORT2_OUTFILE, - BXP_KEYBOARD_USEMAPPING, - BXP_KEYBOARD_MAP, - BXP_KEYBOARD, - BXP_USER_SHORTCUT, - BXP_ASK_FOR_PATHNAME, // for general file selection dialog - BXP_BOCHS_START, // How Bochs starts - // experiment: add params for CPU registers - BXP_CPU_PARAMETERS, - BXP_CPU_EAX, - BXP_CPU_EBX, - BXP_CPU_ECX, - BXP_CPU_EDX, - BXP_CPU_EBP, - BXP_CPU_ESI, - BXP_CPU_EDI, - BXP_CPU_ESP, - BXP_CPU_EIP, - BXP_CPU_SEG_CS, - BXP_CPU_SEG_DS, - BXP_CPU_SEG_SS, - BXP_CPU_SEG_ES, - BXP_CPU_SEG_FS, - BXP_CPU_SEG_GS, - BXP_CPU_SEG_LDTR, - BXP_CPU_SEG_TR, - BXP_CPU_GDTR_BASE, - BXP_CPU_GDTR_LIMIT, - BXP_CPU_IDTR_BASE, - BXP_CPU_IDTR_LIMIT, - BXP_CPU_EFLAGS, - BXP_CPU_EFLAGS_ID, - BXP_CPU_EFLAGS_VIP, - BXP_CPU_EFLAGS_VIF, - BXP_CPU_EFLAGS_AC, - BXP_CPU_EFLAGS_VM, - BXP_CPU_EFLAGS_RF, - BXP_CPU_EFLAGS_NT, - BXP_CPU_EFLAGS_IOPL, - BXP_CPU_EFLAGS_OF, - BXP_CPU_EFLAGS_DF, - BXP_CPU_EFLAGS_IF, - BXP_CPU_EFLAGS_TF, - BXP_CPU_EFLAGS_SF, - BXP_CPU_EFLAGS_ZF, - BXP_CPU_EFLAGS_AF, - BXP_CPU_EFLAGS_PF, - BXP_CPU_EFLAGS_CF, - BXP_CPU_DR0, - BXP_CPU_DR1, - BXP_CPU_DR2, - BXP_CPU_DR3, - BXP_CPU_DR6, - BXP_CPU_DR7, - BXP_CPU_TR3, - BXP_CPU_TR4, - BXP_CPU_TR5, - BXP_CPU_TR6, - BXP_CPU_TR7, - BXP_CPU_CR0, - BXP_CPU_CR1, - BXP_CPU_CR2, - BXP_CPU_CR3, - BXP_CPU_CR4, - // a few parameters for the keyboard - BXP_KBD_PARAMETERS, - BXP_KBD_PARE, - BXP_KBD_TIM , - BXP_KBD_AUXB, - BXP_KBD_KEYL, - BXP_KBD_C_D, - BXP_KBD_SYSF, - BXP_KBD_INPB, - BXP_KBD_OUTB, - BXP_KBD_TIMER_PENDING, - BXP_KBD_IRQ1_REQ, - BXP_KBD_IRQ12_REQ, -#if BX_DEBUGGER - // in debugger, is the simulation running (continue command) or waiting. - // This is only modified by debugger code, not by the user. - BXP_DEBUG_RUNNING, -#endif - BXP_SEL_CONFIG_INTERFACE, - BXP_SEL_DISPLAY_LIBRARY, - BXP_THIS_IS_THE_LAST // used to determine length of list -} bx_id; - -// use x=1,2,3,4 -#define BXP_COMx_ENABLED(x) \ - (bx_id)(BXP_COM1_ENABLED + (((x)-1)*BXP_PARAMS_PER_SERIAL_PORT)) -#define BXP_COMx_PATH(x) \ - (bx_id)(BXP_COM1_PATH + (((x)-1)*BXP_PARAMS_PER_SERIAL_PORT)) - -// use x=1 -#define BXP_USBx_ENABLED(x) \ - (bx_id)(BXP_USB1_ENABLED + (((x)-1)*BXP_PARAMS_PER_USB_HUB)) -#define BXP_USBx_IOADDR(x) \ - (bx_id)(BXP_USB1_IOADDR + (((x)-1)*BXP_PARAMS_PER_USB_HUB)) -#define BXP_USBx_IRQ(x) \ - (bx_id)(BXP_USB1_IRQ + (((x)-1)*BXP_PARAMS_PER_USB_HUB)) - -// use x=1,2 -#define BXP_PARPORTx_ENABLED(x) \ - (bx_id)(BXP_PARPORT1_ENABLED + (((x)-1)*BXP_PARAMS_PER_PARALLEL_PORT)) -#define BXP_PARPORTx_OUTFILE(x) \ - (bx_id)(BXP_PARPORT1_OUTFILE + (((x)-1)*BXP_PARAMS_PER_PARALLEL_PORT)) - -typedef enum { - BX_TOOLBAR_UNDEFINED, - BX_TOOLBAR_FLOPPYA, - BX_TOOLBAR_FLOPPYB, - BX_TOOLBAR_CDROMD, - BX_TOOLBAR_RESET, - BX_TOOLBAR_POWER, - BX_TOOLBAR_COPY, - BX_TOOLBAR_PASTE, - BX_TOOLBAR_SNAPSHOT, - BX_TOOLBAR_CONFIG, - BX_TOOLBAR_MOUSE_EN, - BX_TOOLBAR_USER -} bx_toolbar_buttons; - -// Log level defines -typedef enum { - LOGLEV_DEBUG = 0, - LOGLEV_INFO, - LOGLEV_ERROR, - LOGLEV_PANIC, - LOGLEV_PASS, - N_LOGLEV -} bx_log_levels; - -// types of reset -#define BX_RESET_SOFTWARE 10 -#define BX_RESET_HARDWARE 11 - -//cdrom -#define BX_EJECTED 10 -#define BX_INSERTED 11 - -// boot devices -#define BX_BOOT_FLOPPYA 0 -#define BX_BOOT_DISKC 1 -#define BX_BOOT_CDROM 2 - -// loader hack -#define Load32bitOSNone 0 -#define Load32bitOSLinux 1 -#define Load32bitOSNullKernel 2 // being developed for plex86 -#define Load32bitOSLast 2 - -/////////////////////////////////////////////////////////////////// -// event structures for communication between simulator and CI -/////////////////////////////////////////////////////////////////// -// Because the CI (configuration interface) might be in a different -// thread or even a different process, we pass events encoded in data -// structures to it instead of just calling functions. Each type of -// event is declared as a different structure, and then all those -// structures are squished into a union in BxEvent. (BTW, this is -// almost exactly how X windows event structs work.) -// -// These are simple structs, unblemished by C++ methods and tricks. -// No matter what event type it is, we allocate a BxEvent for each -// one, as opposed to trying to save a few bytes on small events by -// allocating only the bytes necessary for it. This makes it easy and -// fast to store events in a queue, like this -// BxEvent event_queue[MAX_EVENTS]; -// -// Events come in two varieties: synchronous and asynchronous. We -// have to worry about sync and async events because the CI and the -// simulation may be running in different threads. An async event is -// the simplest. Whichever thread originates the event just builds -// the data structure, sends it, and then continues with its business. -// Async events can go in either direction. Synchronous events -// require the other thread to "respond" before the originating thread -// can continue. It's like a function with a return value; you can't -// continue until you get the return value back. -// -// Examples: -// -// async event: In the wxWindows implementation, both the CI and the -// VGAW operate in the wxWindows GUI thread. When the user presses a -// key, wxWindows sends a wxKeyEvent to the VGAW event handler code in -// wx.cc. The VGAW handler then builds a BxEvent with -// type=BX_ASYNC_EVT_KEY, and fills in the bx_key and raw_scancode -// fields. The asynchronous event is placed on the event_queue for -// the simulator, then the VGAW handler returns. (With wxWindows and -// many other graphical libaries, the event handler must return -// quickly because the window will not be updated until it's done.) -// Some time later, the simulator reaches the point where it checks -// for new events from the user (actually controlled by -// bx_keyb_c::periodic() in iodev/keyboard.cc) and calls -// bx_gui.handle_events(). Then all the events in the queue are -// processed by the simulator. There is no "response" sent back to -// the originating thread. -// -// sync event: Sometimes the simulator reaches a point where it needs -// to ask the user how to proceed. In this case, the simulator sends -// a synchronous event because it requires a response before it can -// continue. It builds an event structure, perhaps with type -// BX_SYNC_EVT_ASK_PARAM, sends it to the user interface -// using the event handler function defined by set_notify_callback(), -// and pauses the simulation. The user interface asks the user the -// question, and puts the answer into the BxEvent.retcode field. The -// event handler function returns the modified BxEvent with retcode -// filled in, and the simulation continues. The details of this -// transaction can be complicated if the simulation and CI are not -// in the same thread, but the behavior is as described. -// - -///// types and definitions used in event structures - -#define BX_EVT_IS_ASYNC(type) ((type) > __ALL_EVENTS_BELOW_ARE_ASYNC__) - -typedef enum { - __ALL_EVENTS_BELOW_ARE_SYNCHRONOUS__ = 2000, - BX_SYNC_EVT_GET_PARAM, // CI -> simulator -> CI - BX_SYNC_EVT_ASK_PARAM, // simulator -> CI -> simulator - BX_SYNC_EVT_TICK, // simulator -> CI, wait for response. - BX_SYNC_EVT_LOG_ASK, // simulator -> CI, wait for response. - BX_SYNC_EVT_GET_DBG_COMMAND, // simulator -> CI, wait for response. - __ALL_EVENTS_BELOW_ARE_ASYNC__, - BX_ASYNC_EVT_KEY, // vga window -> simulator - BX_ASYNC_EVT_MOUSE, // vga window -> simulator - BX_ASYNC_EVT_SET_PARAM, // CI -> simulator - BX_ASYNC_EVT_LOG_MSG, // simulator -> CI - BX_ASYNC_EVT_DBG_MSG, // simulator -> CI - BX_ASYNC_EVT_VALUE_CHANGED, // simulator -> CI - BX_ASYNC_EVT_TOOLBAR, // CI -> simulator - BX_ASYNC_EVT_REFRESH // simulator -> CI -} BxEventType; - -typedef union { - Bit32s s32; - char *charptr; -} AnyParamVal; - -// Define substructures which make up the interior of BxEvent. The -// substructures, such as BxKeyEvent or BxMouseEvent, should never be -// allocated on their own. They are only intended to be used within -// the union in the BxEvent structure. - -// Event type: BX_SYNC_EVT_TICK -// -// A tick event is synchronous, sent from the simulator to the GUI. The -// event doesn't do anything visible. Primarily it gives the GUI a chance -// to tell the simulator to quit, if necessary. There may be other uses -// for the tick in the future, such as giving some kind of regular -// status report or mentioning watched values that changed, but so far -// it's just for that one thing. There is no data associated with a -// tick event. - -// Event type: BX_ASYNC_EVT_KEY -// -// A key event can be sent from the VGA window to the Bochs simulator. -// It is asynchronous. -typedef struct { - // what was pressed? This is a BX_KEY_* value. For key releases, - // BX_KEY_RELEASED is ORed with the base BX_KEY_*. - Bit32u bx_key; - bx_bool raw_scancode; -} BxKeyEvent; - -// Event type: BX_ASYNC_EVT_MOUSE -// -// A mouse event can be sent from the VGA window to the Bochs -// simulator. It is asynchronous. Currently unused because mouse -// events aren't implemented in our wxWindows code yet. -typedef struct { - // type is BX_EVT_MOUSE - Bit16s dx, dy; // mouse motion delta - Bit8u buttons; // which buttons are pressed. - // bit 0: 1=left button down, 0=up - // bit 1: 1=right button down, 0=up -} BxMouseEvent; - -// Event type: BX_SYNC_EVT_GET_PARAM, BX_ASYNC_EVT_SET_PARAM -// -// Parameter set/get events are initiated by the CI, since Bochs can -// always access the parameters directly. So far, I haven't used -// these event types. In the CI I just call -// SIM->get_param(parameter_id) to get a pointer to the bx_param_c -// object and then call the get/set methods. This is okay for -// configuration since bochs is not running. However it could be -// dangerous for the GUI thread to poke around in Bochs structures -// while the thread is running. For these cases, I may have to be -// more careful and actually build get/set events and place them on -// Bochs's event queue to be processed during SIM->periodic() or -// something. -typedef struct { - // type is BX_EVT_GET_PARAM, BX_EVT_SET_PARAM - class bx_param_c *param; // pointer to param structure - AnyParamVal val; -} BxParamEvent; - -// Event type: BX_SYNC_EVT_ASK_PARAM -// Synchronous event sent from the simulator to the CI. This tells the -// CI to ask the user to choose the value of a parameter. The CI may -// need to discover the type of parameter so that it can use the right -// kind of graphical display. The BxParamEvent is used for these events -// too. -// FIXME: at the moment the GUI implements the ASK_PARAM event for just -// a few parameter types. I need to implement the event for all parameter -// types. - -// Event type: BX_ASYNC_EVT_VALUE_CHANGED -// -// Asynchronous event sent from the simulator to the CI, telling it that -// some value that it (hopefully) cares about has changed. This isn't -// being used yet, but a good example is in a debugger interface, you might -// want to maintain a reasonably current display of the PC or some other -// simulation state. The CI would set some kind of event mask (which -// doesn't exist now of course) and then when certain values change, the -// simulator would send this event so that the CI can update. We may need -// some kind of "flow control" since the simulator will be able to produce -// new events much faster than the gui can accept them. - -// Event type: BX_ASYNC_EVT_LOG_MSG (unused) -// -// Asynchronous event from the simulator to the CI. When a BX_PANIC, -// BX_ERROR, BX_INFO, or BX_DEBUG is found in the simulator code, this -// event type can be used to inform the CI of the condition. There is -// no point in sending messages to the CI that will not be displayed; these -// would only slow the simulation. So we will need some mechanism for -// choosing what kinds of events will be delivered to the CI. Normally, -// you wouldn't want to look at the log unless something is going wrong. -// At that point, you might want to open up a window to watch the debug -// messages from one or two devices only. -// -// Idea: Except for panics that require user attention to continue, it -// might be most efficient to just append log messages to a file. -// When the user wants to look at the log messages, the gui can reopen -// the file (read only), skip to the end, and look backward for a -// reasonable number of lines to display (200?). This allows it to -// skip over huge bursts of log entries without allocating memory, -// synchronizing threads, etc. for each. -typedef struct { - Bit8u level; - const char *prefix; - const char *msg; -} BxLogMsgEvent; - -// Event type: BX_ASYNC_EVT_DBG_MSG (unused) -// -// Also uses BxLogMsgEvent, but this is a message to be displayed in -// the debugger history window. - -// Event type: BX_SYNC_EVT_LOG_ASK -// -// This is a synchronous version of BX_ASYNC_EVT_LOG_MSG, which is used -// when the "action=ask" setting is used. If the simulator runs into a -// panic, it sends a synchronous BX_SYNC_EVT_LOG_ASK to the CI to be -// displayed. The CI shows a dialog that asks if the user wants to -// continue, quit, etc. and sends the answer back to the simulator. -// This event also uses BxLogMsgEvent. -enum { - BX_LOG_ASK_CHOICE_CONTINUE, - BX_LOG_ASK_CHOICE_CONTINUE_ALWAYS, - BX_LOG_ASK_CHOICE_DIE, - BX_LOG_ASK_CHOICE_DUMP_CORE, - BX_LOG_ASK_CHOICE_ENTER_DEBUG, - BX_LOG_ASK_N_CHOICES -}; - -// Event type: BX_SYNC_EVT_GET_DBG_COMMAND -// -// This is a synchronous event sent from the simulator to the debugger -// requesting the next action. In a text mode debugger, this would prompt -// the user for the next command. When a new command is ready, the -// synchronous event is sent back with its fields filled in. -typedef struct { - char *command; // null terminated string. allocated by debugger interface - // with new operator, freed by simulator with delete. -} BxDebugCommand; - - - -// Event type: BX_EVT_TOOLBAR -// Asynchronous event from the VGAW to the simulator, sent when the user -// clicks on a toolbar button. This may one day become something more -// general, like a command event, but at the moment it's only needed for -// the toolbar events. -typedef struct { - bx_toolbar_buttons button; - bool on; // for toggling buttons, on=true means the toolbar button is - // pressed. on=false means it is not pressed. -} BxToolbarEvent; - -// The BxEvent structure should be used for all events. Every event has -// a type and a spot for a return code (only used for synchronous events). -typedef struct { - BxEventType type; // what kind is this? - Bit32s retcode; // sucess or failure. only used for synchronous events. - union { - BxKeyEvent key; - BxMouseEvent mouse; - BxParamEvent param; - BxLogMsgEvent logmsg; - BxToolbarEvent toolbar; - BxDebugCommand debugcmd; - } u; -} BxEvent; - - -//////////////////////////////////////////////////////////////////// -// parameter classes: bx_param_c and family -//////////////////////////////////////////////////////////////////// -// -// All variables that can be configured through the CI are declared as -// "parameters" or objects of type bx_param_*. There is a bx_param_* -// class for each type of data that the user would need to see and -// edit, e.g. integer, boolean, enum, string, filename, or list of -// other parameters. The purpose of the bx_param_* class, in addition -// to storing the parameter's value, is to hold the name, description, -// and constraints on the value. The bx_param_* class should hold -// everything that the CI would need to display the value and allow -// the user to modify it. For integer parameters, the minimum and -// maximum allowed value can be defined, and the base in which it -// should be displayed and interpreted. For enums, the -// bx_param_enum_c structure includes the list of values which the -// parameter can have. -// -// Also, some parameter classes support get/set callback functions to -// allow arbitrary code to be executed when the parameter is get/set. -// An example of where this is useful: if you disable the NE2K card, -// the set() handler for that parameter can tell the user interface -// that the NE2K's irq, I/O address, and mac address should be -// disabled (greyed out, hidden, or made inaccessible). The get/set -// methods can also check if the set() value is acceptable using -// whatever means and override it. -// -// The parameter concept is similar to the use of parameters in JavaBeans. - -class bx_object_c; -class bx_param_c; -class bx_param_num_c; -class bx_param_enum_c; -class bx_param_bool_c; -class bx_param_string_c; -class bx_param_filename_c; -class bx_list_c; - -class BOCHSAPI bx_object_c { -private: - bx_id id; - bx_objtype type; -protected: - void set_type (bx_objtype type); -public: - bx_object_c (bx_id id); - bx_id get_id () { return id; } - Bit8u get_type () { return type; } -}; - -class BOCHSAPI bx_param_c : public bx_object_c { - BOCHSAPI_CYGONLY static const char *default_text_format; -protected: - char *name; - char *description; - char *label; // label string for text menus and gui dialogs - const char *text_format; // printf format string. %d for ints, %s for strings, etc. - char *ask_format; // format string for asking for a new value - int runtime_param; - int enabled; -public: - bx_param_c (bx_id id, char *name, char *description); - void set_format (const char *format) {text_format = format;} - const char *get_format () {return text_format;} - void set_ask_format (char *format) {ask_format = format; } - char *get_ask_format () {return ask_format;} - void set_label (char *text) {label = text;} - char *get_label () {return label;} - void set_runtime_param (int val) { runtime_param = val; } - int get_runtime_param () { return runtime_param; } - char *get_name () { return name; } - char *get_description () { return description; } - int get_enabled () { return enabled; } - virtual void set_enabled (int enabled) { this->enabled = enabled; } - void reset () {} - int getint () {return -1;} - static const char* set_default_format (const char *f); - static const char *get_default_format () { return default_text_format; } - virtual bx_list_c *get_dependent_list () { return NULL; } -#if BX_UI_TEXT - virtual void text_print (FILE *fp) {} - virtual int text_ask (FILE *fpin, FILE *fpout) {return -1;} -#endif -}; - -typedef Bit64s (*param_event_handler)(class bx_param_c *, int set, Bit64s val); -typedef int (*param_enable_handler)(class bx_param_c *, int en); - -class BOCHSAPI bx_param_num_c : public bx_param_c { - BOCHSAPI_CYGONLY static Bit32u default_base; - // The dependent_list is initialized to NULL. If dependent_list is modified - // to point to a bx_list_c of other parameters, the set() method of - // bx_param_bool_c will enable those parameters when this bool is true, and - // disable them when this bool is false. - bx_list_c *dependent_list; - void update_dependents (); -protected: - Bit64s min, max, initial_val; - union _uval_ { - Bit64s number; // used by bx_param_num_c - Bit64s *p64bit; // used by bx_shadow_num_c - Bit32s *p32bit; // used by bx_shadow_num_c - Bit16s *p16bit; // used by bx_shadow_num_c - Bit8s *p8bit; // used by bx_shadow_num_c - bx_bool *pbool; // used by bx_shadow_bool_c - } val; - param_event_handler handler; - param_enable_handler enable_handler; - int base; - Bit32u options; -public: - enum { - // When a bx_param_num_c is displayed in dialog, USE_SPIN_CONTROL controls - // whether a spin control should be used instead of a simple text control. - USE_SPIN_CONTROL = (1<<0) - } bx_numopt_bits; - bx_param_num_c (bx_id id, - char *name, - char *description, - Bit64s min, Bit64s max, Bit64s initial_val); - void reset (); - void set_handler (param_event_handler handler); - void set_enable_handler (param_enable_handler handler); - virtual bx_list_c *get_dependent_list () { return dependent_list; } - void set_dependent_list (bx_list_c *l); - virtual void set_enabled (int enabled); - virtual Bit32s get () { return (Bit32s) get64(); } - virtual Bit64s get64 (); - virtual void set (Bit64s val); - void set_base (int base) { this->base = base; } - void set_initial_val (Bit64s initial_val); - int get_base () { return base; } - void set_range (Bit64u min, Bit64u max); - Bit64s get_min () { return min; } - Bit64s get_max () { return max; } - static Bit32u set_default_base (Bit32u val); - static Bit32u get_default_base () { return default_base; } - void set_options (Bit32u options) { this->options = options; } - Bit32u get_options () { return options; } -#if BX_UI_TEXT - virtual void text_print (FILE *fp); - virtual int text_ask (FILE *fpin, FILE *fpout); -#endif -}; - -// a bx_shadow_num_c is like a bx_param_num_c except that it doesn't -// store the actual value with its data. Instead, it uses val.p32bit -// to keep a pointer to the actual data. This is used to register -// existing variables as parameters, without have to access it via -// set/get methods. -class BOCHSAPI bx_shadow_num_c : public bx_param_num_c { - Bit8u varsize; // must be 64, 32, 16, or 8 - Bit8u lowbit; // range of bits associated with this param - Bit64u mask; // mask is ANDed with value before it is returned from get -public: - bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit64s *ptr_to_real_val, - Bit8u highbit = 63, - Bit8u lowbit = 0); - bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit64u *ptr_to_real_val, - Bit8u highbit = 63, - Bit8u lowbit = 0); - bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit32s *ptr_to_real_val, - Bit8u highbit = 31, - Bit8u lowbit = 0); - bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit32u *ptr_to_real_val, - Bit8u highbit = 31, - Bit8u lowbit = 0); - bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit16s *ptr_to_real_val, - Bit8u highbit = 15, - Bit8u lowbit = 0); - bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit16u *ptr_to_real_val, - Bit8u highbit = 15, - Bit8u lowbit = 0); - bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit8s *ptr_to_real_val, - Bit8u highbit = 7, - Bit8u lowbit = 0); - bx_shadow_num_c (bx_id id, - char *name, - char *description, - Bit8u *ptr_to_real_val, - Bit8u highbit = 7, - Bit8u lowbit = 0); - virtual Bit64s get64 (); - virtual void set (Bit64s val); -}; - -class BOCHSAPI bx_param_bool_c : public bx_param_num_c { - // many boolean variables are used to enable/disable modules. In the - // user interface, the enable variable should enable/disable all the - // other parameters associated with that module. -public: - bx_param_bool_c (bx_id id, - char *name, - char *description, - Bit64s initial_val); -#if BX_UI_TEXT - virtual void text_print (FILE *fp); - virtual int text_ask (FILE *fpin, FILE *fpout); -#endif -}; - -// a bx_shadow_bool_c is a shadow param based on bx_param_bool_c. -class BOCHSAPI bx_shadow_bool_c : public bx_param_bool_c { - // each bit of a bitfield can be a separate value. bitnum tells which - // bit is used. get/set will only modify that bit. - Bit8u bitnum; -public: - bx_shadow_bool_c (bx_id id, - char *name, - char *description, - bx_bool *ptr_to_real_val, - Bit8u bitnum = 0); - virtual Bit64s get64 (); - virtual void set (Bit64s val); -}; - - -class BOCHSAPI bx_param_enum_c : public bx_param_num_c { - char **choices; -public: - bx_param_enum_c (bx_id id, - char *name, - char *description, - char **choices, - Bit64s initial_val, - Bit64s value_base = 0); - char *get_choice (int n) { return choices[n]; } - int find_by_name (const char *string); - bool set_by_name (const char *string); -#if BX_UI_TEXT - virtual void text_print (FILE *fp); - virtual int text_ask (FILE *fpin, FILE *fpout); -#endif -}; - -typedef char* (*param_string_event_handler)(class bx_param_string_c *, int set, char *val, int maxlen); - -class BOCHSAPI bx_param_string_c : public bx_param_c { - int maxsize; - char *val, *initial_val; - param_string_event_handler handler; - param_enable_handler enable_handler; - bx_param_num_c *options; - char separator; -public: - enum { - RAW_BYTES = 1, // use binary text editor, like MAC addr - IS_FILENAME = 2, // 1=yes it's a filename, 0=not a filename. - // Some guis have a file browser. This - // bit suggests that they use it. - SAVE_FILE_DIALOG = 4 // Use save dialog opposed to open file dialog - } bx_string_opt_bits; - bx_param_string_c (bx_id id, - char *name, - char *description, - char *initial_val, - int maxsize=-1); - virtual ~bx_param_string_c (); - void reset (); - void set_handler (param_string_event_handler handler); - void set_enable_handler (param_enable_handler handler); - virtual void set_enabled (int enabled); - Bit32s get (char *buf, int len); - char *getptr () {return val; } - void set (char *buf); - bx_bool equals (const char *buf); - bx_param_num_c *get_options () { return options; } - void set_separator (char sep) {separator = sep; } - char get_separator () {return separator; } - int get_maxsize () {return maxsize; } -#if BX_UI_TEXT - virtual void text_print (FILE *fp); - virtual int text_ask (FILE *fpin, FILE *fpout); -#endif -}; - -// Declare a filename class. It is identical to a string, except that -// it initializes the options differently. This is just a shortcut -// for declaring a string param and setting the options with IS_FILENAME. -class BOCHSAPI bx_param_filename_c : public bx_param_string_c { -public: - bx_param_filename_c (bx_id id, - char *name, - char *description, - char *initial_val, - int maxsize=-1); -}; - -class BOCHSAPI bx_list_c : public bx_param_c { -private: - // just a list of bx_param_c objects. size tells current number of - // objects in the list, and maxsize tells how many list items are - // allocated in the constructor. - bx_param_c **list; - int size, maxsize; - // options is a bit field whose bits are defined by bx_listopt_bits ORed - // together. Options is a bx_param so that if necessary the bx_list could - // install a handler to cause get/set of options to have side effects. - bx_param_num_c *options; - // for a menu, the value of choice before the call to "ask" is default. - // After ask, choice holds the value that the user chose. Choice defaults - // to 1 in the constructor. - bx_param_num_c *choice; - // title of the menu or series - bx_param_string_c *title; - // if the menu shows a "return to previous menu" type of choice, - // this controls where that choice will go. - bx_param_c *parent; - void init (); -public: - enum { - // When a bx_list_c is displayed as a menu, SHOW_PARENT controls whether or - // not the menu shows a "Return to parent menu" choice or not. - SHOW_PARENT = (1<<0), - // Some lists are best displayed shown as menus, others as a series of - // related questions. This bit suggests to the CI that the series of - // questions format is preferred. - SERIES_ASK = (1<<1), - // When a bx_list_c is displayed in a dialog, USE_TAB_WINDOW suggests - // to the CI that each item in the list should be shown as a separate - // tab. This would be most appropriate when each item is another list - // of parameters. - USE_TAB_WINDOW = (1<<2), - // When a bx_list_c is displayed in a dialog, the list name is used as the - // label of the group box if USE_BOX_TITLE is set. This is only necessary if - // more than one list appears in a dialog box. - USE_BOX_TITLE = (1<<3) - } bx_listopt_bits; - bx_list_c (bx_id id, int maxsize); - bx_list_c (bx_id id, char *name, char *description, bx_param_c **init_list); - bx_list_c (bx_id id, char *name, char *description, int maxsize); - virtual ~bx_list_c(); - bx_list_c *clone (); - void add (bx_param_c *param); - bx_param_c *get (int index); - int get_size () { return size; } - bx_param_num_c *get_options () { return options; } - void set_options (bx_param_num_c *newopt) { options = newopt; } - bx_param_num_c *get_choice () { return choice; } - bx_param_string_c *get_title () { return title; } - void set_parent (bx_param_c *newparent) { parent = newparent; } - bx_param_c *get_parent () { return parent; } -#if BX_UI_TEXT - virtual void text_print (FILE *); - virtual int text_ask (FILE *fpin, FILE *fpout); -#endif -}; - -//////////////////////////////////////////////////////////////// - - -// These are the different start modes. -enum { - // Just start the simulation without running the configuration interface - // at all, unless something goes wrong. - BX_QUICK_START = 200, - // Run the configuration interface. The default action will be to load a - // configuration file. This makes sense if a config file could not be - // loaded, either because it wasn't found or because it had errors. - BX_LOAD_START, - // Run the configuration interface. The default action will be to - // edit the configuration. - BX_EDIT_START, - // Run the configuration interface, but make the default action be to - // start the simulation. - BX_RUN_START -}; - -#define BX_FLOPPY_NONE 10 // floppy not present -#define BX_FLOPPY_1_2 11 // 1.2M 5.25" -#define BX_FLOPPY_1_44 12 // 1.44M 3.5" -#define BX_FLOPPY_2_88 13 // 2.88M 3.5" -#define BX_FLOPPY_720K 14 // 720K 3.5" -#define BX_FLOPPY_360K 15 // 360K 5.25" -#define BX_FLOPPY_160K 16 // 160K 5.25" -#define BX_FLOPPY_180K 17 // 180K 5.25" -#define BX_FLOPPY_320K 18 // 320K 5.25" -#define BX_FLOPPY_LAST 18 // last legal value of floppy type - -#define BX_FLOPPY_GUESS 20 // decide based on image size - -#define BX_ATA_DEVICE_DISK 0 -#define BX_ATA_DEVICE_CDROM 1 -#define BX_ATA_DEVICE_LAST 1 - -#define BX_ATA_BIOSDETECT_NONE 0 -#define BX_ATA_BIOSDETECT_AUTO 1 -#define BX_ATA_BIOSDETECT_CMOS 2 - -#define BX_ATA_TRANSLATION_NONE 0 -#define BX_ATA_TRANSLATION_LBA 1 -#define BX_ATA_TRANSLATION_LARGE 2 -#define BX_ATA_TRANSLATION_RECHS 3 -#define BX_ATA_TRANSLATION_AUTO 4 -#define BX_ATA_TRANSLATION_LAST 4 - -#define BX_ATA_MODE_FLAT 0 -#define BX_ATA_MODE_CONCAT 1 -#define BX_ATA_MODE_EXTDISKSIM 2 -#define BX_ATA_MODE_DLL_HD 3 -#define BX_ATA_MODE_SPARSE 4 -#define BX_ATA_MODE_VMWARE3 5 -#define BX_ATA_MODE_UNDOABLE 6 -#define BX_ATA_MODE_GROWING 7 -#define BX_ATA_MODE_VOLATILE 8 -#define BX_ATA_MODE_LAST 8 -//#define BX_ATA_MODE_Z_UNDOABLE 9 -//#define BX_ATA_MODE_Z_VOLATILE 10 -//#define BX_ATA_MODE_SPLIT 6 - -#define BX_CLOCK_SYNC_NONE 0 -#define BX_CLOCK_SYNC_REALTIME 1 -#define BX_CLOCK_SYNC_SLOWDOWN 2 -#define BX_CLOCK_SYNC_BOTH 3 -#define BX_CLOCK_SYNC_LAST 3 - -#define BX_CLOCK_TIME0_LOCAL 1 -#define BX_CLOCK_TIME0_UTC 2 - -BOCHSAPI extern char *bochs_start_names[]; -BOCHSAPI extern int n_bochs_start_names; -BOCHSAPI extern char *floppy_type_names[]; -BOCHSAPI extern int floppy_type_n_sectors[]; -BOCHSAPI extern int n_floppy_type_names; -BOCHSAPI extern char *floppy_status_names[]; -BOCHSAPI extern int n_floppy_status_names; -BOCHSAPI extern char *floppy_bootdisk_names[]; -BOCHSAPI extern int n_floppy_bootdisk_names; -BOCHSAPI extern char *loader_os_names[]; -BOCHSAPI extern int n_loader_os_names; -BOCHSAPI extern char *keyboard_type_names[]; -BOCHSAPI extern int n_keyboard_type_names; -BOCHSAPI extern char *atadevice_type_names[]; -BOCHSAPI extern int n_atadevice_type_names; -BOCHSAPI extern char *atadevice_mode_names[]; -BOCHSAPI extern int n_atadevice_mode_names; -BOCHSAPI extern char *atadevice_status_names[]; -BOCHSAPI extern int n_atadevice_status_names; -BOCHSAPI extern char *atadevice_biosdetect_names[]; -BOCHSAPI extern int n_atadevice_biosdetect_names; -BOCHSAPI extern char *atadevice_translation_names[]; -BOCHSAPI extern int n_atadevice_translation_names; -BOCHSAPI extern char *clock_sync_names[]; -BOCHSAPI extern int clock_sync_n_names; - -typedef struct { - bx_param_enum_c *Odevtype; - bx_param_string_c *Opath; - bx_param_enum_c *Otype; - bx_param_enum_c *Ostatus; - } bx_floppy_options; - -typedef struct { - bx_list_c *Omenu; - bx_param_bool_c *Opresent; - bx_param_enum_c *Otype; - bx_param_enum_c *Omode; - bx_param_string_c *Opath; - bx_param_string_c *Ojournal; - bx_param_num_c *Ocylinders; - bx_param_num_c *Oheads; - bx_param_num_c *Ospt; - bx_param_enum_c *Ostatus; - bx_param_string_c *Omodel; - bx_param_enum_c *Obiosdetect; - bx_param_enum_c *Otranslation; - } bx_atadevice_options; - -typedef struct { - bx_param_bool_c *Oenabled; - bx_param_string_c *Odev; - } bx_serial_options; - -typedef struct { - bx_param_bool_c *Oenabled; - bx_param_num_c *Oioaddr; - bx_param_num_c *Oirq; - } bx_usb_options; - - -//////////////////////////////////////////////////////////////////// -// base class simulator interface, contains just virtual functions. -// I'm not longer sure that having a base class is going to be of any -// use... -Bryce - -#include - -enum ci_command_t { CI_START, CI_RUNTIME_CONFIG, CI_SHUTDOWN }; -enum ci_return_t { - CI_OK, // normal return value - CI_ERR_NO_TEXT_CONSOLE // err: can't work because there's no text console - }; -typedef int (*config_interface_callback_t)(void *userdata, ci_command_t command); - -// bx_gui->set_display_mode() changes the mode between the configuration -// interface and the simulation. This is primarily intended for display -// libraries which have a full-screen mode such as SDL, term, and svgalib. The -// display mode is set to DISP_MODE_CONFIG before displaying any configuration -// menus, for panics that requires user input, when entering the debugger, etc. -// It is set to DISP_MODE_SIM when the Bochs simulation resumes. The constants -// are defined here so that configuration interfaces can use them with the -// bx_simulator_interface_c::set_display_mode() method. -enum disp_mode_t { DISP_MODE_CONFIG=100, DISP_MODE_SIM }; - -class BOCHSAPI bx_simulator_interface_c { -public: - bx_simulator_interface_c (); - virtual void set_quit_context (jmp_buf *context) {} - virtual int get_init_done () { return -1; } - virtual int set_init_done (int n) {return -1;} - virtual void get_param_id_range (int *min, int *max) {} - virtual int register_param (bx_id id, bx_param_c *it) {return -1;} - virtual void reset_all_param () {} - virtual bx_param_c *get_param (bx_id id) {return NULL;} - virtual bx_param_num_c *get_param_num (bx_id id) {return NULL;} - virtual bx_param_string_c *get_param_string (bx_id id) {return NULL;} - virtual bx_param_bool_c *get_param_bool (bx_id id) {return NULL;} - virtual bx_param_enum_c *get_param_enum (bx_id id) {return NULL;} - virtual int get_n_log_modules () {return -1;} - virtual char *get_prefix (int mod) {return 0;} - virtual int get_log_action (int mod, int level) {return -1;} - virtual void set_log_action (int mod, int level, int action) {} - virtual int get_default_log_action (int level) {return -1;} - virtual void set_default_log_action (int level, int action) {} - virtual char *get_action_name (int action) {return 0;} - virtual const char *get_log_level_name (int level) {return 0;} - virtual int get_max_log_level () {return -1;} - - // exiting is somewhat complicated! The preferred way to exit bochs is - // to call BX_EXIT(exitcode). That is defined to call - // SIM->quit_sim(exitcode). The quit_sim function first calls - // the cleanup functions in bochs so that it can destroy windows - // and free up memory, then sends a notify message to the CI - // telling it that bochs has stopped. - virtual void quit_sim (int code) {} - - virtual int get_exit_code () { return 0; } - - virtual int get_default_rc (char *path, int len) {return -1;} - virtual int read_rc (char *path) {return -1;} - virtual int write_rc (char *rc, int overwrite) {return -1;} - virtual int get_log_file (char *path, int len) {return -1;} - virtual int set_log_file (char *path) {return -1;} - virtual int get_log_prefix (char *prefix, int len) {return -1;} - virtual int set_log_prefix (char *prefix) {return -1;} - virtual int get_debugger_log_file (char *path, int len) {return -1;} - virtual int set_debugger_log_file (char *path) {return -1;} - virtual int get_floppy_options (int drive, bx_floppy_options *out) {return -1;} - virtual int get_cdrom_options (int drive, bx_atadevice_options *out, int *where = NULL) {return -1;} - virtual char *get_floppy_type_name (int type) {return NULL;} - - // The CI calls set_notify_callback to register its event handler function. - // This event handler function is called whenever the simulator needs to - // send an event to the CI. For example, if the simulator hits a panic and - // wants to ask the user how to proceed, it would call the CI event handler - // to ask the CI to display a dialog. - // - // NOTE: At present, the standard VGAW buttons (floppy, snapshot, power, - // etc.) are displayed and handled by gui.cc, not by the CI or siminterface. - // gui.cc uses its own callback functions to implement the behavior of - // the buttons. Some of these implementations call the siminterface. - typedef BxEvent* (*bxevent_handler)(void *theclass, BxEvent *event); - virtual void set_notify_callback (bxevent_handler func, void *arg) {} - virtual void get_notify_callback (bxevent_handler *func, void **arg) {} - - // send an event from the simulator to the CI. - virtual BxEvent* sim_to_ci_event (BxEvent *event) {return NULL;} - - // called from simulator when it hits serious errors, to ask if the user - // wants to continue or not - virtual int log_msg (const char *prefix, int level, const char *msg) {return -1;} - - // tell the CI to ask the user for the value of a parameter. - virtual int ask_param (bx_id param) {return -1;} - - // ask the user for a pathname - virtual int ask_filename (char *filename, int maxlen, char *prompt, char *the_default, int flags) {return -1;} - // called at a regular interval, currently by the keyboard handler. - virtual void periodic () {} - virtual int create_disk_image (const char *filename, int sectors, bx_bool overwrite) {return -3;} - // Tell the configuration interface (CI) that some parameter values have - // changed. The CI will reread the parameters and change its display if it's - // appropriate. Maybe later: mention which params have changed to save time. - virtual void refresh_ci () {} - // forces a vga update. This was added so that a debugger can force - // a vga update when single stepping, without having to wait thousands - // of cycles for the normal vga refresh triggered by iodev/keyboard.cc. - virtual void refresh_vga () {} - // forces a call to bx_gui.handle_events. This was added so that a debugger - // can force the gui events to be handled, so that interactive things such - // as a toolbar click will be processed. - virtual void handle_events () {} - // return first hard disk in ATA interface - virtual bx_param_c *get_first_cdrom () {return NULL;} - // return first cdrom in ATA interface - virtual bx_param_c *get_first_hd () {return NULL;} -#if BX_DEBUGGER - // for debugger: same behavior as pressing control-C - virtual void debug_break () {} - virtual void debug_interpret_cmd (char *cmd) {} - virtual char *debug_get_next_command () {return NULL;} - virtual void debug_puts (const char *text) {} -#endif - virtual void register_configuration_interface ( - const char* name, - config_interface_callback_t callback, - void *userdata) {} - virtual int configuration_interface(const char* name, ci_command_t command) {return -1; } - virtual int begin_simulation (int argc, char *argv[]) {return -1;} - typedef bool (*is_sim_thread_func_t)(); - is_sim_thread_func_t is_sim_thread_func; - virtual void set_sim_thread_func (is_sim_thread_func_t func) { - is_sim_thread_func = func; - } - virtual bool is_sim_thread () {return true;} - virtual bool is_wx_selected () {return false;} - // provide interface to bx_gui->set_display_mode() method for config - // interfaces to use. - virtual void set_display_mode (disp_mode_t newmode) {} - virtual bool test_for_text_console () { return true; } -}; - -BOCHSAPI extern bx_simulator_interface_c *SIM; - -BOCHSAPI extern void bx_init_siminterface (); -BOCHSAPI extern int bx_init_main (int argc, char *argv[]); - -#if defined(__WXMSW__) || defined(WIN32) -// Just to provide HINSTANCE, etc. in files that have not included bochs.h. -// I don't like this at all, but I don't see a way around it. -#include -#endif - -// define structure to hold data that is passed into our main function. -typedef struct BOCHSAPI { - // standard argc,argv - int argc; - char **argv; -#ifdef WIN32 - char initial_dir[MAX_PATH]; -#endif -#ifdef __WXMSW__ - // these are only used when compiling with wxWindows. This gives us a - // place to store the data that was passed to WinMain. - HINSTANCE hInstance; - HINSTANCE hPrevInstance; - LPSTR m_lpCmdLine; - int nCmdShow; -#endif -} bx_startup_flags_t; - -BOCHSAPI extern bx_startup_flags_t bx_startup_flags; -BOCHSAPI extern bx_bool bx_user_quit; diff --git a/tools/ioemu/gui/svga.cc b/tools/ioemu/gui/svga.cc deleted file mode 100644 index 33020fca80..0000000000 --- a/tools/ioemu/gui/svga.cc +++ /dev/null @@ -1,514 +0,0 @@ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -#define _MULTI_THREAD - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_WITH_SVGA - -#include -#include -#include -#include -#include - -#include "font/vga.bitmap.h" -//#include "icon_bochs.h" - -class bx_svga_gui_c : public bx_gui_c { -public: - bx_svga_gui_c (void); - DECLARE_GUI_VIRTUAL_METHODS() - virtual void set_display_mode (disp_mode_t newmode); -}; - -// declare one instance of the gui object and call macro to insert the -// plugin code -static bx_svga_gui_c *theGui = NULL; - -IMPLEMENT_GUI_PLUGIN_CODE(svga) - -#define LOG_THIS theGui-> - -static unsigned res_x, res_y; -static int fontwidth = 8, fontheight = 16; -static unsigned tilewidth, tileheight; -static unsigned char vgafont[256 * 16]; -static int clut8 = 0; -GraphicsContext *screen = NULL; -static int save_vga_mode; -static int save_vga_pal[256 * 3]; - -void keyboard_handler(int scancode, int press); -void mouse_handler(int button, int dx, int dy, int dz, - int drx, int dry, int drz); - -unsigned char reverse_byteorder(unsigned char b) -{ - unsigned char ret = 0; - - for (unsigned i=0;i<8;i++){ - ret |= (b & 0x01) << (7 - i); - b >>= 1; - } - return ret; -} - -void create_vga_font() -{ - memcpy(vgafont, bx_vgafont, sizeof(bx_vgafont)); - - for (unsigned i=0;i< sizeof(bx_vgafont);i++) { - vgafont[i] = reverse_byteorder(vgafont[i]); - } -} - -bx_svga_gui_c::bx_svga_gui_c () -{ - put("SVGA"); -} - -void bx_svga_gui_c::specific_init( - int argc, - char **argv, - unsigned x_tilesize, - unsigned y_tilesize, - unsigned header_bar_y) -{ - tilewidth = x_tilesize; - tileheight = y_tilesize; - - if(vga_init() != 0 ) - { - LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL); - BX_PANIC (("Unable to initialize SVGAlib")); - return; - } - - screen = gl_allocatecontext(); - - dimension_update(640,400); - create_vga_font(); - gl_setfont(8, 16, (void *)vgafont); - gl_setwritemode(FONT_COMPRESSED); - - keyboard_init(); - keyboard_seteventhandler((__keyboard_handler) keyboard_handler); - - vga_setmousesupport(1); - mouse_seteventhandler((__mouse_handler) mouse_handler); - if (vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_FLAGS) & VGA_CLUT8) { - vga_ext_set(VGA_EXT_SET, VGA_CLUT8); - clut8 = 1; - } - // Save settings to prepare for mode transition in set_display_mode. - // If DISP_MODE_SIM is called first, these values will be used. - save_vga_mode = vga_getcurrentmode(); - vga_getpalvec(0, 256, save_vga_pal); -} - -void bx_svga_gui_c::text_update( - Bit8u *old_text, - Bit8u *new_text, - unsigned long cursor_x, - unsigned long cursor_y, - bx_vga_tminfo_t tm_info, - unsigned rows) -{ - unsigned x, y, i; - unsigned chars, cols; - char s[] = " "; - static unsigned int previ; - unsigned int cursori; - - cols = res_x/fontwidth; - - cursori = (cursor_y*cols + cursor_x) * 2; - - chars = cols*rows; - - for (i=0; i> 4); - } else { - gl_setfontcolors((new_text[i+1] & 0xF0) >> 4, new_text[i+1] & 0x0F); - } - gl_write(x * fontwidth, y * fontheight, s); - } - } - previ = cursori; -} - - int -bx_svga_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes) -{ - return 0; -} - - int -bx_svga_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len) -{ - return 0; -} - - -void bx_svga_gui_c::graphics_tile_update( - Bit8u *snapshot, - unsigned x, - unsigned y) -{ - gl_putbox(x, y, tilewidth, tileheight, snapshot); -} - -static Bit32u vga_to_bx_key(int key) -{ - switch (key) { - case SCANCODE_ESCAPE: return BX_KEY_ESC; - case SCANCODE_1: return BX_KEY_1; - case SCANCODE_2: return BX_KEY_2; - case SCANCODE_3: return BX_KEY_3; - case SCANCODE_4: return BX_KEY_4; - case SCANCODE_5: return BX_KEY_5; - case SCANCODE_6: return BX_KEY_6; - case SCANCODE_7: return BX_KEY_7; - case SCANCODE_8: return BX_KEY_8; - case SCANCODE_9: return BX_KEY_9; - case SCANCODE_0: return BX_KEY_0; - - case SCANCODE_MINUS: return BX_KEY_MINUS; - case SCANCODE_EQUAL: return BX_KEY_EQUALS; - case SCANCODE_TAB: return BX_KEY_TAB; - case SCANCODE_BACKSPACE: return BX_KEY_BACKSPACE; - - case SCANCODE_Q: return BX_KEY_Q; - case SCANCODE_W: return BX_KEY_W; - case SCANCODE_E: return BX_KEY_E; - case SCANCODE_R: return BX_KEY_R; - case SCANCODE_T: return BX_KEY_T; - case SCANCODE_Y: return BX_KEY_Y; - case SCANCODE_U: return BX_KEY_U; - case SCANCODE_I: return BX_KEY_I; - case SCANCODE_O: return BX_KEY_O; - case SCANCODE_P: return BX_KEY_P; - - case SCANCODE_BRACKET_LEFT: return BX_KEY_LEFT_BRACKET; - case SCANCODE_BRACKET_RIGHT: return BX_KEY_RIGHT_BRACKET; - - case SCANCODE_ENTER: return BX_KEY_ENTER; - case SCANCODE_LEFTCONTROL: return BX_KEY_CTRL_L; - - case SCANCODE_A: return BX_KEY_A; - case SCANCODE_S: return BX_KEY_S; - case SCANCODE_D: return BX_KEY_D; - case SCANCODE_F: return BX_KEY_F; - case SCANCODE_G: return BX_KEY_G; - case SCANCODE_H: return BX_KEY_H; - case SCANCODE_J: return BX_KEY_J; - case SCANCODE_K: return BX_KEY_K; - case SCANCODE_L: return BX_KEY_L; - - case SCANCODE_SEMICOLON: return BX_KEY_SEMICOLON; - case SCANCODE_APOSTROPHE: return BX_KEY_SINGLE_QUOTE; - case SCANCODE_GRAVE: return BX_KEY_GRAVE; - - case SCANCODE_LEFTSHIFT: return BX_KEY_SHIFT_L; - case SCANCODE_BACKSLASH: return BX_KEY_BACKSLASH; - - case SCANCODE_Z: return BX_KEY_Z; - case SCANCODE_X: return BX_KEY_X; - case SCANCODE_C: return BX_KEY_C; - case SCANCODE_V: return BX_KEY_V; - case SCANCODE_B: return BX_KEY_B; - case SCANCODE_N: return BX_KEY_N; - case SCANCODE_M: return BX_KEY_M; - - case SCANCODE_COMMA: return BX_KEY_COMMA; - case SCANCODE_PERIOD: return BX_KEY_PERIOD; - case SCANCODE_SLASH: return BX_KEY_SLASH; - - case SCANCODE_RIGHTSHIFT: return BX_KEY_SHIFT_R; - case SCANCODE_KEYPADMULTIPLY: return BX_KEY_KP_MULTIPLY; - - case SCANCODE_LEFTALT: return BX_KEY_ALT_L; - case SCANCODE_SPACE: return BX_KEY_SPACE; - case SCANCODE_CAPSLOCK: return BX_KEY_CAPS_LOCK; - - case SCANCODE_F1: return BX_KEY_F1; - case SCANCODE_F2: return BX_KEY_F2; - case SCANCODE_F3: return BX_KEY_F3; - case SCANCODE_F4: return BX_KEY_F4; - case SCANCODE_F5: return BX_KEY_F5; - case SCANCODE_F6: return BX_KEY_F6; - case SCANCODE_F7: return BX_KEY_F7; - case SCANCODE_F8: return BX_KEY_F8; - case SCANCODE_F9: return BX_KEY_F9; - case SCANCODE_F10: return BX_KEY_F10; - - case SCANCODE_NUMLOCK: return BX_KEY_NUM_LOCK; - case SCANCODE_SCROLLLOCK: return BX_KEY_SCRL_LOCK; - - case SCANCODE_KEYPAD7: return BX_KEY_KP_HOME; - case SCANCODE_KEYPAD8: return BX_KEY_KP_UP; - case SCANCODE_KEYPAD9: return BX_KEY_KP_PAGE_UP; - case SCANCODE_KEYPADMINUS: return BX_KEY_KP_SUBTRACT; - case SCANCODE_KEYPAD4: return BX_KEY_KP_LEFT; - case SCANCODE_KEYPAD5: return BX_KEY_KP_5; - case SCANCODE_KEYPAD6: return BX_KEY_KP_RIGHT; - case SCANCODE_KEYPADPLUS: return BX_KEY_KP_ADD; - case SCANCODE_KEYPAD1: return BX_KEY_KP_END; - case SCANCODE_KEYPAD2: return BX_KEY_KP_DOWN; - case SCANCODE_KEYPAD3: return BX_KEY_KP_PAGE_DOWN; - case SCANCODE_KEYPAD0: return BX_KEY_KP_INSERT; -// case SCANCODE_KEYPADPERIOD: return BX_KEY_KP_; /* ??? */ - -// case SCANCODE_LESS: return BX_KEY_KP_LESS; /* ??? */ - - case SCANCODE_F11: return BX_KEY_F11; - case SCANCODE_F12: return BX_KEY_F12; - - case SCANCODE_KEYPADENTER: return BX_KEY_KP_ENTER; - case SCANCODE_RIGHTCONTROL: return BX_KEY_CTRL_R; - case SCANCODE_KEYPADDIVIDE: return BX_KEY_KP_DIVIDE; - case SCANCODE_PRINTSCREEN: return BX_KEY_PRINT; - case SCANCODE_RIGHTALT: return BX_KEY_ALT_R; - case SCANCODE_BREAK: return BX_KEY_PAUSE; - - case SCANCODE_HOME: return BX_KEY_HOME; - case SCANCODE_CURSORBLOCKUP: return BX_KEY_UP; - case SCANCODE_PAGEUP: return BX_KEY_PAGE_UP; - case SCANCODE_CURSORBLOCKLEFT: return BX_KEY_LEFT; - case SCANCODE_CURSORBLOCKRIGHT: return BX_KEY_RIGHT; - case SCANCODE_END: return BX_KEY_END; - case SCANCODE_CURSORBLOCKDOWN: return BX_KEY_DOWN; - case SCANCODE_PAGEDOWN: return BX_KEY_PAGE_DOWN; - case SCANCODE_INSERT: return BX_KEY_INSERT; - case SCANCODE_REMOVE: return BX_KEY_DELETE; - - case SCANCODE_RIGHTWIN: return BX_KEY_WIN_R; - case SCANCODE_LEFTWIN: return BX_KEY_WIN_L; - - default: return 0; - } -} - -void keyboard_handler(int scancode, int press) -{ - if (scancode != SCANCODE_F12) { - int bx_key = vga_to_bx_key(scancode); - Bit32u key_state; - - if (press) { - key_state = BX_KEY_PRESSED; - } else { - key_state = BX_KEY_RELEASED; - } - - DEV_kbd_gen_scancode(bx_key | key_state); - } else { - BX_INFO(("F12 pressed")); - // show runtime options menu, which uses stdin/stdout - SIM->configuration_interface (NULL, CI_RUNTIME_CONFIG); - } -} - -void mouse_handler(int button, int dx, int dy, int dz, - int drx, int dry, int drz) -{ - int buttons = 0; - - if (button & MOUSE_LEFTBUTTON) { - buttons |= 0x01; - } - - if (button & MOUSE_RIGHTBUTTON) { - buttons |= 0x02; - } - DEV_mouse_motion((int) (0.25 * dx), (int) -(0.25 * dy), buttons); -} - -void bx_svga_gui_c::handle_events(void) -{ - keyboard_update(); - keyboard_clearstate(); - mouse_update(); -} - -void bx_svga_gui_c::flush(void) -{ - gl_copyscreen(screen); -} - -void bx_svga_gui_c::clear_screen(void) -{ - gl_clearscreen(0); -} - -bx_bool bx_svga_gui_c::palette_change( - unsigned index, - unsigned red, - unsigned green, - unsigned blue) -{ - if( index > 255 ) return 0; - - // without VGA_CLUT8 extension we have only 6 bits for each r,g,b value - if (!clut8 && (red > 63 || green > 63 || blue > 63)) { - red = red >> 2; - green = green >> 2; - blue = blue >> 2; - } - - vga_setpalette(index, red, green, blue); - - return 1; -} - - -void bx_svga_gui_c::dimension_update( - unsigned x, - unsigned y, - unsigned fheight, - unsigned fwidth, - unsigned bpp) -{ - int newmode = 0; - - if (bpp > 8) { - BX_PANIC(("%d bpp graphics mode not supported yet", bpp)); - } - if( fheight > 0 ) - { - fontheight = fheight; - if (fwidth != 8) { - x = x * 8 / fwidth; - } - fontwidth = 8; - } - - if( (x == res_x) && (y == res_y )) return; - - if (x == 640 && y == 480) { - newmode = G640x480x256; - } else if (x == 640 && y == 400) { - newmode = G640x400x256; - } else if (x == 320 && y == 200) { - newmode = G320x200x256; - } - - if (!vga_hasmode(newmode)) { - newmode = G640x480x256; // trying "default" mode... - } - - if (vga_setmode(newmode) != 0) - { - LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL); - BX_PANIC (("Unable to set requested videomode: %ix%i", x, y)); - } - - gl_setcontextvga(newmode); - gl_getcontext(screen); - gl_setcontextvgavirtual(newmode); - save_vga_mode = newmode; - - res_x = x; - res_y = y; -} - - -unsigned bx_svga_gui_c::create_bitmap( - const unsigned char *bmap, - unsigned xdim, - unsigned ydim) -{ - return 0; -} - - -unsigned bx_svga_gui_c::headerbar_bitmap( - unsigned bmap_id, - unsigned alignment, - void (*f)(void)) -{ - return 0; -} - - -void bx_svga_gui_c::replace_bitmap( - unsigned hbar_id, - unsigned bmap_id) -{ -} - - -void bx_svga_gui_c::show_headerbar(void) -{ -} - - -void bx_svga_gui_c::mouse_enabled_changed_specific (bx_bool val) -{ -} - - -void headerbar_click(int x) -{ -} - -void bx_svga_gui_c::exit(void) -{ - vga_setmode(TEXT); - keyboard_close(); - mouse_close(); -} - -void -bx_svga_gui_c::set_display_mode (disp_mode_t newmode) -{ - // if no mode change, do nothing. - if (disp_mode == newmode) return; - // remember the display mode for next time - disp_mode = newmode; - switch (newmode) { - case DISP_MODE_CONFIG: - BX_DEBUG (("switch to configuration mode (back to console)")); - // remember old values and switch to text mode - save_vga_mode = vga_getcurrentmode(); - vga_getpalvec(0, 256, save_vga_pal); - keyboard_close(); - vga_setmode(TEXT); - break; - case DISP_MODE_SIM: - BX_DEBUG (("switch to simulation mode (fullscreen)")); - keyboard_init(); - keyboard_seteventhandler((__keyboard_handler) keyboard_handler); - vga_setmode(save_vga_mode); - vga_setpalvec(0, 256, save_vga_pal); - break; - } -} - -#endif /* if BX_WITH_SVGA */ diff --git a/tools/ioemu/gui/term.cc b/tools/ioemu/gui/term.cc deleted file mode 100644 index 37bf9c5936..0000000000 --- a/tools/ioemu/gui/term.cc +++ /dev/null @@ -1,843 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: term.cc,v 1.31 2003/08/17 23:40:38 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2000 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_WITH_TERM - -#include "icon_bochs.h" - -extern "C" { -#include -#include -}; - -class bx_term_gui_c : public bx_gui_c { -public: - bx_term_gui_c (void) {} - DECLARE_GUI_VIRTUAL_METHODS() - - virtual Bit32u get_sighandler_mask (); - // called when registered signal arrives - virtual void sighandler (int sig); -}; - -// declare one instance of the gui object and call macro to insert the -// plugin code -static bx_term_gui_c *theGui = NULL; -IMPLEMENT_GUI_PLUGIN_CODE(term) - -#define LOG_THIS theGui-> - -bx_bool initialized = 0; -static unsigned int text_cols = 80, text_rows = 25; - -static short curses_color[8] = { - /* 0 */ COLOR_BLACK, - /* 1 */ COLOR_BLUE, - /* 2 */ COLOR_GREEN, - /* 3 */ COLOR_CYAN, - /* 4 */ COLOR_RED, - /* 5 */ COLOR_MAGENTA, - /* 6 */ COLOR_YELLOW, - /* 7 */ COLOR_WHITE -}; - -static chtype vga_to_term[128] = { - 0xc7, 0xfc, 0xe9, 0xe2, 0xe4, 0xe0, 0xe5, 0xe7, - 0xea, 0xeb, 0xe8, 0xef, 0xee, 0xec, 0xc4, 0xc5, - 0xc9, 0xe6, 0xc6, 0xf4, 0xf6, 0xf2, 0xfb, 0xf9, - 0xff, 0xd6, 0xdc, 0xe7, 0xa3, 0xa5, ' ', ' ', - 0xe1, 0xed, 0xf3, 0xfa, 0xf1, 0xd1, 0xaa, 0xba, - 0xbf, ' ', 0xac, ' ', ' ', 0xa1, 0xab, 0xbb, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, ' ', ' ', ' ', ' ', - ' ', ' ', ' ', ' ', ' ', ' ', 0xb5, ' ', - ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', - ' ', 0xb1, ' ', ' ', ' ', ' ', 0xf7, ' ', - 0xb0, ' ', ' ', ' ', ' ', 0xb2, ' ', ' ' -}; - -static void -do_scan(int key_event, int shift, int ctrl, int alt) -{ - /* XXX At some point, cache alt/ctrl/shift so only when the state - changes do we simulate a press or release, to cut down on - keyboard input to the simulated machine */ - - BX_DEBUG(("key_event %d/0x%x %s%s%s", - key_event,key_event, - shift?"(shift)":"", - ctrl?"(ctrl)":"", - alt?"(alt)":"")); - if(shift) - DEV_kbd_gen_scancode(BX_KEY_SHIFT_L); - if(ctrl) - DEV_kbd_gen_scancode(BX_KEY_CTRL_L); - if(alt) - DEV_kbd_gen_scancode(BX_KEY_ALT_L); - DEV_kbd_gen_scancode(key_event); - key_event |= BX_KEY_RELEASED; - - DEV_kbd_gen_scancode(key_event); - if(alt) - DEV_kbd_gen_scancode(BX_KEY_ALT_L|BX_KEY_RELEASED); - if(ctrl) - DEV_kbd_gen_scancode(BX_KEY_CTRL_L|BX_KEY_RELEASED); - if(shift) - DEV_kbd_gen_scancode(BX_KEY_SHIFT_L|BX_KEY_RELEASED); -} - -Bit32u -bx_term_gui_c::get_sighandler_mask () -{ - return - (1<set_log_action(LOGLEV_PANIC, ACT_FATAL); - // logfile should be different from stderr, otherwise terminal mode - // really ends up having fun - if (!strcmp(bx_options.log.Ofilename->getptr(), "-")) - BX_PANIC(("cannot log to stderr in term mode")); - - initscr(); - start_color(); - cbreak(); - curs_set(2); - keypad(stdscr,TRUE); - nodelay(stdscr, TRUE); - noecho(); - -#if BX_HAVE_COLOR_SET - if (has_colors()) { - for (int i=0; iget ()) - BX_ERROR(("WARNING: private_colormap option ignored.")); - initialized = 1; -} - - - -void -do_char(int character,int alt) -{ - switch (character) { - // control keys - case 0x9: do_scan(BX_KEY_TAB,0,0,alt); break; - case 0xa: do_scan(BX_KEY_KP_ENTER,0,0,alt); break; - case 0xd: do_scan(BX_KEY_KP_DELETE,0,0,alt); break; - case 0x1: do_scan(BX_KEY_A,0,1,alt); break; - case 0x2: do_scan(BX_KEY_B,0,1,alt); break; - case 0x3: do_scan(BX_KEY_C,0,1,alt); break; - case 0x4: do_scan(BX_KEY_D,0,1,alt); break; - case 0x5: do_scan(BX_KEY_E,0,1,alt); break; - case 0x6: do_scan(BX_KEY_F,0,1,alt); break; - case 0x7: do_scan(BX_KEY_G,0,1,alt); break; - case 0x8: do_scan(BX_KEY_H,0,1,alt); break; - case 0xb: do_scan(BX_KEY_K,0,1,alt); break; - case 0xc: do_scan(BX_KEY_L,0,1,alt); break; - case 0xe: do_scan(BX_KEY_N,0,1,alt); break; - case 0xf: do_scan(BX_KEY_O,0,1,alt); break; - case 0x10: do_scan(BX_KEY_P,0,1,alt); break; - case 0x11: do_scan(BX_KEY_Q,0,1,alt); break; - case 0x12: do_scan(BX_KEY_R,0,1,alt); break; - case 0x13: do_scan(BX_KEY_S,0,1,alt); break; - case 0x14: do_scan(BX_KEY_T,0,1,alt); break; - case 0x15: do_scan(BX_KEY_U,0,1,alt); break; - case 0x16: do_scan(BX_KEY_V,0,1,alt); break; - case 0x17: do_scan(BX_KEY_W,0,1,alt); break; - case 0x18: do_scan(BX_KEY_X,0,1,alt); break; - case 0x19: do_scan(BX_KEY_Y,0,1,alt); break; - case 0x1a: do_scan(BX_KEY_Z,0,1,alt); break; - case 0x20: do_scan(BX_KEY_SPACE,0,0,alt); break; - case 0x107: do_scan(BX_KEY_BACKSPACE,0,0,alt); break; - case 0x102: do_scan(BX_KEY_DOWN,0,0,alt); break; - case 0x103: do_scan(BX_KEY_UP,0,0,alt); break; - case 0x104: do_scan(BX_KEY_LEFT,0,0,alt); break; - case 0x105: do_scan(BX_KEY_RIGHT,0,0,alt); break; - case 0x152: do_scan(BX_KEY_PAGE_DOWN,0,0,alt); break; - case 0x153: do_scan(BX_KEY_PAGE_UP,0,0,alt); break; - case 0x106: do_scan(BX_KEY_HOME,0,0,alt); break; - case 0x168: do_scan(BX_KEY_END,0,0,alt); break; - case 0x14b: do_scan(BX_KEY_INSERT,0,0,alt); break; - case 0x7f: do_scan(BX_KEY_DELETE,0,0,alt); break; - case 0x1b: do_scan(BX_KEY_ESC,0,0,alt); break; - case '!': do_scan(BX_KEY_1,1,0,alt); break; - case '\'': do_scan(BX_KEY_SINGLE_QUOTE,0,0,alt); break; - case '#': do_scan(BX_KEY_3,1,0,alt); break; - case '$': do_scan(BX_KEY_4,1,0,alt); break; - case '%': do_scan(BX_KEY_5,1,0,alt); break; - case '^': do_scan(BX_KEY_6,1,0,alt); break; - case '&': do_scan(BX_KEY_7,1,0,alt); break; - case '"': do_scan(BX_KEY_SINGLE_QUOTE,1,0,alt); break; - - // ()*+,-./ - case '(': do_scan(BX_KEY_9,1,0,alt); break; - case ')': do_scan(BX_KEY_0,1,0,alt); break; - case '*': do_scan(BX_KEY_8,1,0,alt); break; - case '+': do_scan(BX_KEY_EQUALS,1,0,alt); break; - case ',': do_scan(BX_KEY_COMMA,0,0,alt); break; - case '-': do_scan(BX_KEY_MINUS,0,0,alt); break; - case '.': do_scan(BX_KEY_PERIOD,0,0,alt); break; - case '/': do_scan(BX_KEY_SLASH,0,0,alt); break; - - // 01234567 - case '0': do_scan(BX_KEY_0,0,0,alt); break; - case '1': do_scan(BX_KEY_1,0,0,alt); break; - case '2': do_scan(BX_KEY_2,0,0,alt); break; - case '3': do_scan(BX_KEY_3,0,0,alt); break; - case '4': do_scan(BX_KEY_4,0,0,alt); break; - case '5': do_scan(BX_KEY_5,0,0,alt); break; - case '6': do_scan(BX_KEY_6,0,0,alt); break; - case '7': do_scan(BX_KEY_7,0,0,alt); break; - - // 89:;<=>? - case '8': do_scan(BX_KEY_8,0,0,alt); break; - case '9': do_scan(BX_KEY_9,0,0,alt); break; - case ':': do_scan(BX_KEY_SEMICOLON,1,0,alt); break; - case ';': do_scan(BX_KEY_SEMICOLON,0,0,alt); break; - case '<': do_scan(BX_KEY_COMMA,1,0,alt); break; - case '=': do_scan(BX_KEY_EQUALS,0,0,alt); break; - case '>': do_scan(BX_KEY_PERIOD,1,0,alt); break; - case '?': do_scan(BX_KEY_SLASH,1,0,alt); break; - - // @ABCDEFG - case '@': do_scan(BX_KEY_2,1,0,alt); break; - case 'A': do_scan(BX_KEY_A,1,0,alt); break; - case 'B': do_scan(BX_KEY_B,1,0,alt); break; - case 'C': do_scan(BX_KEY_C,1,0,alt); break; - case 'D': do_scan(BX_KEY_D,1,0,alt); break; - case 'E': do_scan(BX_KEY_E,1,0,alt); break; - case 'F': do_scan(BX_KEY_F,1,0,alt); break; - case 'G': do_scan(BX_KEY_G,1,0,alt); break; - - - // HIJKLMNO - case 'H': do_scan(BX_KEY_H,1,0,alt); break; - case 'I': do_scan(BX_KEY_I,1,0,alt); break; - case 'J': do_scan(BX_KEY_J,1,0,alt); break; - case 'K': do_scan(BX_KEY_K,1,0,alt); break; - case 'L': do_scan(BX_KEY_L,1,0,alt); break; - case 'M': do_scan(BX_KEY_M,1,0,alt); break; - case 'N': do_scan(BX_KEY_N,1,0,alt); break; - case 'O': do_scan(BX_KEY_O,1,0,alt); break; - - - // PQRSTUVW - case 'P': do_scan(BX_KEY_P,1,0,alt); break; - case 'Q': do_scan(BX_KEY_Q,1,0,alt); break; - case 'R': do_scan(BX_KEY_R,1,0,alt); break; - case 'S': do_scan(BX_KEY_S,1,0,alt); break; - case 'T': do_scan(BX_KEY_T,1,0,alt); break; - case 'U': do_scan(BX_KEY_U,1,0,alt); break; - case 'V': do_scan(BX_KEY_V,1,0,alt); break; - case 'W': do_scan(BX_KEY_W,1,0,alt); break; - - // XYZ[\]^_ - case 'X': do_scan(BX_KEY_X,1,0,alt); break; - case 'Y': do_scan(BX_KEY_Y,1,0,alt); break; - case 'Z': do_scan(BX_KEY_Z,1,0,alt); break; - case '{': do_scan(BX_KEY_LEFT_BRACKET,1,0,alt); break; - case '|': do_scan(BX_KEY_BACKSLASH,1,0,alt); break; - case '}': do_scan(BX_KEY_RIGHT_BRACKET,1,0,alt); break; - case '_': do_scan(BX_KEY_MINUS,1,0,alt); break; - - // `abcdefg - case '`': do_scan(BX_KEY_GRAVE,0,0,alt); break; - case 'a': do_scan(BX_KEY_A,0,0,alt); break; - case 'b': do_scan(BX_KEY_B,0,0,alt); break; - case 'c': do_scan(BX_KEY_C,0,0,alt); break; - case 'd': do_scan(BX_KEY_D,0,0,alt); break; - case 'e': do_scan(BX_KEY_E,0,0,alt); break; - case 'f': do_scan(BX_KEY_F,0,0,alt); break; - case 'g': do_scan(BX_KEY_G,0,0,alt); break; - - // hijklmno - case 'h': do_scan(BX_KEY_H,0,0,alt); break; - case 'i': do_scan(BX_KEY_I,0,0,alt); break; - case 'j': do_scan(BX_KEY_J,0,0,alt); break; - case 'k': do_scan(BX_KEY_K,0,0,alt); break; - case 'l': do_scan(BX_KEY_L,0,0,alt); break; - case 'm': do_scan(BX_KEY_M,0,0,alt); break; - case 'n': do_scan(BX_KEY_N,0,0,alt); break; - case 'o': do_scan(BX_KEY_O,0,0,alt); break; - - // pqrstuvw - case 'p': do_scan(BX_KEY_P,0,0,alt); break; - case 'q': do_scan(BX_KEY_Q,0,0,alt); break; - case 'r': do_scan(BX_KEY_R,0,0,alt); break; - case 's': do_scan(BX_KEY_S,0,0,alt); break; - case 't': do_scan(BX_KEY_T,0,0,alt); break; - case 'u': do_scan(BX_KEY_U,0,0,alt); break; - case 'v': do_scan(BX_KEY_V,0,0,alt); break; - case 'w': do_scan(BX_KEY_W,0,0,alt); break; - - // xyz{|}~ - case 'x': do_scan(BX_KEY_X,0,0,alt); break; - case 'y': do_scan(BX_KEY_Y,0,0,alt); break; - case 'z': do_scan(BX_KEY_Z,0,0,alt); break; - case '[': do_scan(BX_KEY_LEFT_BRACKET,0,0,alt); break; - case '\\': do_scan(BX_KEY_BACKSLASH,0,0,alt); break; - case ']': do_scan(BX_KEY_RIGHT_BRACKET,0,0,alt); break; - case '~': do_scan(BX_KEY_GRAVE,1,0,alt); break; - - // function keys - case KEY_F(1): do_scan(BX_KEY_F1,0,0,alt); break; - case KEY_F(2): do_scan(BX_KEY_F2,0,0,alt); break; - case KEY_F(3): do_scan(BX_KEY_F3,0,0,alt); break; - case KEY_F(4): do_scan(BX_KEY_F4,0,0,alt); break; - case KEY_F(5): do_scan(BX_KEY_F5,0,0,alt); break; - case KEY_F(6): do_scan(BX_KEY_F6,0,0,alt); break; - case KEY_F(7): do_scan(BX_KEY_F7,0,0,alt); break; - case KEY_F(8): do_scan(BX_KEY_F8,0,0,alt); break; - case KEY_F(9): do_scan(BX_KEY_F9,0,0,alt); break; - case KEY_F(10): do_scan(BX_KEY_F10,0,0,alt); break; - case KEY_F(11): do_scan(BX_KEY_F11,0,0,alt); break; - case KEY_F(12): do_scan(BX_KEY_F12,0,0,alt); break; - - // shifted function keys - case KEY_F(13): do_scan(BX_KEY_F1,1,0,alt); break; - case KEY_F(14): do_scan(BX_KEY_F2,1,0,alt); break; - case KEY_F(15): do_scan(BX_KEY_F3,1,0,alt); break; - case KEY_F(16): do_scan(BX_KEY_F4,1,0,alt); break; - case KEY_F(17): do_scan(BX_KEY_F5,1,0,alt); break; - case KEY_F(18): do_scan(BX_KEY_F6,1,0,alt); break; - case KEY_F(19): do_scan(BX_KEY_F7,1,0,alt); break; - case KEY_F(20): do_scan(BX_KEY_F8,1,0,alt); break; - - default: - if(character > 0x79) { - do_char(character - 0x80,1); - break; - } - - BX_INFO(("character unhandled: 0x%x",character)); - break; - } -} - - -// ::HANDLE_EVENTS() -// -// Called periodically (vga_update_interval in .bochsrc) so the -// the gui code can poll for keyboard, mouse, and other -// relevant events. - - void -bx_term_gui_c::handle_events(void) -{ - int character; - while((character = getch()) != ERR) { - BX_DEBUG(("scancode(0x%x)",character)); - do_char(character,0); - } -} - - - -// ::FLUSH() -// -// Called periodically, requesting that the gui code flush all pending -// screen update requests. - - void -bx_term_gui_c::flush(void) -{ - if (initialized) - refresh(); -} - - -// ::CLEAR_SCREEN() -// -// Called to request that the VGA region is cleared. Don't -// clear the area that defines the headerbar. - - void -bx_term_gui_c::clear_screen(void) -{ - clear(); -#if BX_HAVE_COLOR_SET - color_set(7, NULL); -#endif -#if BX_HAVE_MVHLINE - if (LINES > (int)text_rows) { - mvhline(text_rows, 0, ACS_HLINE, text_cols); - } -#endif -#if BX_HAVE_MVVLINE - if (COLS > (int)text_cols) { - mvvline(0, text_cols, ACS_VLINE, text_rows); - } -#endif - if ((LINES > (int)text_rows) && (COLS > (int)text_cols)) { - mvaddch(text_rows, text_cols, ACS_LRCORNER); - } -} - -int -get_color_pair(Bit8u vga_attr) -{ - int term_attr; - - term_attr = curses_color[vga_attr & 0x07]; - term_attr |= (curses_color[(vga_attr & 0x70) >> 4] << 3); - return term_attr; -} - -chtype -get_term_char(Bit8u vga_char[]) -{ - int term_char; - - if ((vga_char[1] & 0x0f) == ((vga_char[1] >> 4) & 0x0f)) { - return ' '; - } - switch (vga_char[0]) { - case 0x04: term_char = ACS_DIAMOND; break; - case 0x18: term_char = ACS_UARROW; break; - case 0x19: term_char = ACS_DARROW; break; - case 0x1a: term_char = ACS_RARROW; break; - case 0x1b: term_char = ACS_LARROW; break; - case 0xc4: - case 0xcd: term_char = ACS_HLINE; break; - case 0xb3: - case 0xba: term_char = ACS_VLINE; break; - case 0xc9: - case 0xd5: - case 0xd6: - case 0xda: term_char = ACS_ULCORNER; break; - case 0xb7: - case 0xb8: - case 0xbb: - case 0xbf: term_char = ACS_URCORNER; break; - case 0xc0: - case 0xc8: - case 0xd3: - case 0xd4: term_char = ACS_LLCORNER; break; - case 0xbc: - case 0xbd: - case 0xbe: - case 0xd9: term_char = ACS_LRCORNER; break; - case 0xc3: - case 0xc6: - case 0xc7: - case 0xcc: term_char = ACS_LTEE; break; - case 0xb4: - case 0xb5: - case 0xb6: - case 0xb9: term_char = ACS_RTEE; break; - case 0xc2: - case 0xcb: - case 0xd1: - case 0xd2: term_char = ACS_TTEE; break; - case 0xc1: - case 0xca: - case 0xcf: - case 0xd0: term_char = ACS_BTEE; break; - case 0xc5: - case 0xce: - case 0xd7: - case 0xd8: term_char = ACS_PLUS; break; - case 0xb0: - case 0xb1: term_char = ACS_CKBOARD; break; - case 0xb2: term_char = ACS_BOARD; break; - case 0xdb: term_char = ACS_BLOCK; break; - default: - if (vga_char[0] > 0x7f) { - term_char = vga_to_term[vga_char[0]-0x80]; - } else if (vga_char[0] > 0x1f) { - term_char = vga_char[0]; - } else { - term_char = ' '; - } - } - return term_char; -} - -// ::TEXT_UPDATE() -// -// Called in a VGA text mode, to update the screen with -// new content. -// -// old_text: array of character/attributes making up the contents -// of the screen from the last call. See below -// new_text: array of character/attributes making up the current -// contents, which should now be displayed. See below -// -// format of old_text & new_text: each is 4000 bytes long. -// This represents 80 characters wide by 25 high, with -// each character being 2 bytes. The first by is the -// character value, the second is the attribute byte. -// I currently don't handle the attribute byte. -// -// cursor_x: new x location of cursor -// cursor_y: new y location of cursor - - void -bx_term_gui_c::text_update(Bit8u *old_text, Bit8u *new_text, - unsigned long cursor_x, unsigned long cursor_y, - bx_vga_tminfo_t tm_info, unsigned nrows) -{ - unsigned char *old_line, *new_line, *new_start; - unsigned char cAttr; - unsigned int hchars, rows, x, y; - chtype ch; - bx_bool force_update = 0; - - UNUSED(nrows); - - if(charmap_updated) { - force_update = 1; - charmap_updated = 0; - } - - new_start = new_text; - rows = text_rows; - y = 0; - do { - hchars = text_cols; - new_line = new_text; - old_line = old_text; - x = 0; - do { - if (force_update || (old_text[0] != new_text[0]) - || (old_text[1] != new_text[1])) { -#if BX_HAVE_COLOR_SET - if (has_colors()) { - color_set(get_color_pair(new_text[1]), NULL); - } -#endif - ch = get_term_char(&new_text[0]); - if ((new_text[1] & 0x08) > 0) ch |= A_BOLD; - if ((new_text[1] & 0x80) > 0) ch |= A_BLINK; - mvaddch(y, x, ch); - } - x++; - new_text+=2; - old_text+=2; - } while (--hchars); - y++; - new_text = new_line + tm_info.line_offset; - old_text = old_line + tm_info.line_offset; - } while (--rows); - - if ((cursor_x0) - cursor_x--; - else { - cursor_x=COLS-1; - cursor_y--; - } - cAttr = new_start[cursor_y*tm_info.line_offset+cursor_x*2+1]; -#if BX_HAVE_COLOR_SET - if (has_colors()) { - color_set(get_color_pair(cAttr), NULL); - } -#endif - ch = get_term_char(&new_start[cursor_y*tm_info.line_offset+cursor_x*2]); - if ((cAttr & 0x08) > 0) ch |= A_BOLD; - if ((cAttr & 0x80) > 0) ch |= A_REVERSE; - mvaddch(cursor_y, cursor_x, ch); - curs_set(2); - } else { - curs_set(0); - } -} - - int -bx_term_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes) -{ - return 0; -} - - int -bx_term_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len) -{ - return 0; -} - - -// ::PALETTE_CHANGE() -// -// Allocate a color in the native GUI, for this color, and put -// it in the colormap location 'index'. -// returns: 0=no screen update needed (color map change has direct effect) -// 1=screen updated needed (redraw using current colormap) - - bx_bool -bx_term_gui_c::palette_change(unsigned index, unsigned red, unsigned green, unsigned blue) -{ - BX_DEBUG(("color pallete request (%d,%d,%d,%d) ignored", - index,red,green,blue)); - return(0); -} - - -// ::GRAPHICS_TILE_UPDATE() -// -// Called to request that a tile of graphics be drawn to the -// screen, since info in this region has changed. -// -// tile: array of 8bit values representing a block of pixels with -// dimension equal to the 'tilewidth' & 'tileheight' parameters to -// ::specific_init(). Each value specifies an index into the -// array of colors you allocated for ::palette_change() -// x0: x origin of tile -// y0: y origin of tile -// -// note: origin of tile and of window based on (0,0) being in the upper -// left of the window. - - void -bx_term_gui_c::graphics_tile_update(Bit8u *tile, unsigned x0, unsigned y0) -{ - UNUSED(tile); - UNUSED(x0); - UNUSED(y0); -} - - - -// ::DIMENSION_UPDATE() -// -// Called when the VGA mode changes it's X,Y dimensions. -// Resize the window to this size, but you need to add on -// the height of the headerbar to the Y value. -// -// x: new VGA x size -// y: new VGA y size (add headerbar_y parameter from ::specific_init(). -// fheight: new VGA character height in text mode -// fwidth : new VGA character width in text mode -// bpp : bits per pixel in graphics mode - - void -bx_term_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, unsigned fwidth, unsigned bpp) -{ - if (bpp > 8) { - BX_PANIC(("%d bpp graphics mode not supported", bpp)); - } - if (fheight > 0) { - text_cols = x / fwidth; - text_rows = y / fheight; -#if BX_HAVE_COLOR_SET - color_set(7, NULL); -#endif -#if BX_HAVE_MVHLINE - if (LINES > (int)text_rows) { - mvhline(text_rows, 0, ACS_HLINE, text_cols); - } -#endif -#if BX_HAVE_MVVLINE - if (COLS > (int)text_cols) { - mvvline(0, text_cols, ACS_VLINE, text_rows); - } -#endif - if ((LINES > (int)text_rows) && (COLS > (int)text_cols)) { - mvaddch(text_rows, text_cols, ACS_LRCORNER); - } - } -} - - -// ::CREATE_BITMAP() -// -// Create a monochrome bitmap of size 'xdim' by 'ydim', which will -// be drawn in the headerbar. Return an integer ID to the bitmap, -// with which the bitmap can be referenced later. -// -// bmap: packed 8 pixels-per-byte bitmap. The pixel order is: -// bit0 is the left most pixel, bit7 is the right most pixel. -// xdim: x dimension of bitmap -// ydim: y dimension of bitmap - - unsigned -bx_term_gui_c::create_bitmap(const unsigned char *bmap, unsigned xdim, unsigned ydim) -{ - UNUSED(bmap); - UNUSED(xdim); - UNUSED(ydim); - return(0); -} - - -// ::HEADERBAR_BITMAP() -// -// Called to install a bitmap in the bochs headerbar (toolbar). -// -// bmap_id: will correspond to an ID returned from -// ::create_bitmap(). 'alignment' is either BX_GRAVITY_LEFT -// or BX_GRAVITY_RIGHT, meaning install the bitmap in the next -// available leftmost or rightmost space. -// alignment: is either BX_GRAVITY_LEFT or BX_GRAVITY_RIGHT, -// meaning install the bitmap in the next -// available leftmost or rightmost space. -// f: a 'C' function pointer to callback when the mouse is clicked in -// the boundaries of this bitmap. - - unsigned -bx_term_gui_c::headerbar_bitmap(unsigned bmap_id, unsigned alignment, void (*f)(void)) -{ - UNUSED(bmap_id); - UNUSED(alignment); - UNUSED(f); - return(0); -} - - -// ::SHOW_HEADERBAR() -// -// Show (redraw) the current headerbar, which is composed of -// currently installed bitmaps. - - void -bx_term_gui_c::show_headerbar(void) -{ -} - - -// ::REPLACE_BITMAP() -// -// Replace the bitmap installed in the headerbar ID slot 'hbar_id', -// with the one specified by 'bmap_id'. 'bmap_id' will have -// been generated by ::create_bitmap(). The old and new bitmap -// must be of the same size. This allows the bitmap the user -// sees to change, when some action occurs. For example when -// the user presses on the floppy icon, it then displays -// the ejected status. -// -// hbar_id: headerbar slot ID -// bmap_id: bitmap ID - - void -bx_term_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id) -{ - UNUSED(hbar_id); - UNUSED(bmap_id); -} - - -// ::EXIT() -// -// Called before bochs terminates, to allow for a graceful -// exit from the native GUI mechanism. - - void -bx_term_gui_c::exit(void) -{ - if (!initialized) return; - clear(); - flush(); - endwin(); - BX_DEBUG(("exiting")); -} - - void -bx_term_gui_c::mouse_enabled_changed_specific (bx_bool val) -{ -} -#endif /* if BX_WITH_TERM */ diff --git a/tools/ioemu/gui/textconfig.cc b/tools/ioemu/gui/textconfig.cc deleted file mode 100644 index 7b5b098453..0000000000 --- a/tools/ioemu/gui/textconfig.cc +++ /dev/null @@ -1,995 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: textconfig.cc,v 1.18 2003/10/24 15:39:57 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// This is code for a text-mode configuration interface. Note that this file -// does NOT include bochs.h. Instead, it does all of its contact with -// the simulator through an object called SIM, defined in siminterface.cc -// and siminterface.h. This separation adds an extra layer of method -// calls before any work can be done, but the benefit is that the compiler -// enforces the rules. I can guarantee that textconfig.cc doesn't call any -// I/O device objects directly, for example, because the bx_devices symbol -// isn't even defined in this context. -// - -#include "config.h" - -extern "C" { -#include -#include -#include -#include -} -#include "osdep.h" -#include "textconfig.h" -#include "siminterface.h" -#include "extplugin.h" -#ifdef WIN32 -#include "win32dialog.h" -#endif - -#define CI_PATH_LENGTH 512 - -#define BX_INSERTED 11 - -/* functions for changing particular options */ -void bx_config_interface_init (); -int bx_read_rc (char *rc); -int bx_write_rc (char *rc); -void bx_log_options (int individual); - -/******************************************************************/ -/* lots of code stolen from bximage.c */ -/* remove leading spaces, newline junk at end. returns pointer to - cleaned string, which is between s0 and the null */ -char * -clean_string (char *s0) -{ - char *s = s0; - char *ptr; - /* find first nonblank */ - while (isspace (*s)) - s++; - /* truncate string at first non-alphanumeric */ - ptr = s; - while (isprint (*ptr)) - ptr++; - *ptr = 0; - return s; -} - -void -double_percent (char *s, int max_len) -{ - char d[CI_PATH_LENGTH]; - int i=0,j=0; - - if (max_len>CI_PATH_LENGTH) - max_len=CI_PATH_LENGTH; - - max_len--; - - while((s[i]!=0)&&(jmax) { - printf ("Your choice (%s) was not an integer between %u and %u.\n\n", - clean, min, max); - } else { - // choice is okay - *out = n; - return 0; - } - } -} - -// identical to ask_uint, but uses signed comparisons -int -ask_int (char *prompt, Bit32s min, Bit32s max, Bit32s the_default, Bit32s *out) -{ - int n = max + 1; - char buffer[1024]; - char *clean; - int illegal; - while (1) { - printf (prompt, the_default); - if (!fgets (buffer, sizeof(buffer), stdin)) - return -1; - clean = clean_string (buffer); - if (strlen(clean) < 1) { - // empty line, use the default - *out = the_default; - return 0; - } - illegal = (1 != sscanf (buffer, "%d", &n)); - if (illegal || nmax) { - printf ("Your choice (%s) was not an integer between %d and %d.\n\n", - clean, min, max); - } else { - // choice is okay - *out = n; - return 0; - } - } -} - -int -ask_menu (char *prompt, int n_choices, char *choice[], int the_default, int *out) -{ - char buffer[1024]; - char *clean; - int i; - *out = -1; - while (1) { - printf (prompt, choice[the_default]); - if (!fgets (buffer, sizeof(buffer), stdin)) - return -1; - clean = clean_string (buffer); - if (strlen(clean) < 1) { - // empty line, use the default - *out = the_default; - return 0; - } - for (i=0; i0) printf (", "); - printf ("%s", choice[i]); - } - printf ("\n"); - } -} - -int -ask_yn (char *prompt, Bit32u the_default, Bit32u *out) -{ - char buffer[16]; - char *clean; - *out = 1<<31; - while (1) { - // if there's a %s field, substitute in the default yes/no. - printf (prompt, the_default ? "yes" : "no"); - if (!fgets (buffer, sizeof(buffer), stdin)) - return -1; - clean = clean_string (buffer); - if (strlen(clean) < 1) { - // empty line, use the default - *out = the_default; - return 0; - } - switch (tolower(clean[0])) { - case 'y': *out=1; return 0; - case 'n': *out=0; return 0; - } - printf ("Please type either yes or no.\n"); - } -} - -// returns -1 on error (stream closed or something) -// returns 0 if default was taken -// returns 1 if value changed -int -ask_string (char *prompt, char *the_default, char *out) -{ - char buffer[1024]; - char *clean; - assert (the_default != out); - out[0] = 0; - printf (prompt, the_default); - if (fgets (buffer, sizeof(buffer), stdin) == NULL) - return -1; - clean = clean_string (buffer); - if (strlen(clean) < 1) { - // empty line, use the default - strcpy (out, the_default); - return 0; - } - strcpy (out, clean); - return 1; -} - -/******************************************************************/ - -static char *startup_menu_prompt = -"------------------------------\n" -"Bochs Configuration: Main Menu\n" -"------------------------------\n" -"\n" -"This is the Bochs Configuration Interface, where you can describe the\n" -"machine that you want to simulate. Bochs has already searched for a\n" -"configuration file (typically called bochsrc.txt) and loaded it if it\n" -"could be found. When you are satisfied with the configuration, go\n" -"ahead and start the simulation.\n" -"\n" -"You can also start bochs with the -q option to skip these menus.\n" -"\n" -"1. Restore factory default configuration\n" -"2. Read options from...\n" -"3. Edit options\n" -"4. Save options to...\n" -"5. Begin simulation\n" -"6. Quit now\n" -"\n" -"Please choose one: [%d] "; - -static char *startup_options_prompt = -"------------------\n" -"Bochs Options Menu\n" -"------------------\n" -"0. Return to previous menu\n" -"1. Log file: %s\n" -"2. Log prefix: %s\n" -"3. Debug log file: %s\n" -"4. Log options for all devices\n" -"5. Log options for individual devices\n" -"6. Memory options\n" -"7. Interface options\n" -"8. Disk options\n" -"9. Serial or Parallel port options\n" -"10. Sound Blaster 16 options\n" -"11. NE2000 network card options\n" -"12. Keyboard options\n" -"13. Other options\n" -"\n" -"Please choose one: [0] "; - -static char *runtime_menu_prompt = -"---------------------\n" -"Bochs Runtime Options\n" -"---------------------\n" -"1. Floppy disk 0: %s\n" -"2. Floppy disk 1: %s\n" -"3. 1st CDROM: %s\n" -"4. 2nd CDROM: %s\n" -"5. 3rd CDROM: %s\n" -"6. 4th CDROM: %s\n" -"7. (not implemented)\n" -"8. Log options for all devices\n" -"9. Log options for individual devices\n" -"10. VGA Update Interval: %d\n" -"11. Mouse: %s\n" -"12. Keyboard paste delay: %d\n" -"13. Userbutton shortcut: %s\n" -"14. Instruction tracing: off (doesn't exist yet)\n" -"15. Continue simulation\n" -"16. Quit now\n" -"\n" -"Please choose one: [15] "; - -#define NOT_IMPLEMENTED(choice) \ - fprintf (stderr, "ERROR: choice %d not implemented\n", choice); - -#define BAD_OPTION(menu,choice) \ - do {fprintf (stderr, "ERROR: menu %d has no choice %d\n", menu, choice); \ - assert (0); } while (0) - -void build_runtime_options_prompt (char *format, char *buf, int size) -{ - bx_floppy_options floppyop; - bx_atadevice_options cdromop; -/* bx_param_num_c *ips = SIM->get_param_num (BXP_IPS); */ - char buffer[6][128]; - for (int i=0; i<2; i++) { - SIM->get_floppy_options (i, &floppyop); - if (floppyop.Odevtype->get () == BX_FLOPPY_NONE) - strcpy (buffer[i], "(not present)"); - else { - sprintf (buffer[i], "%s, size=%s, %s", floppyop.Opath->getptr (), - SIM->get_floppy_type_name (floppyop.Otype->get ()), - (floppyop.Ostatus->get () == BX_INSERTED)? "inserted" : "ejected"); - if (!floppyop.Opath->getptr ()[0]) strcpy (buffer[i], "none"); - } - } - - // 4 cdroms supported at run time - int device; - for (Bit8u cdrom=0; cdrom<4; cdrom++) { - if (!SIM->get_cdrom_options (cdrom, &cdromop, &device) || !cdromop.Opresent->get ()) - sprintf (buffer[2+cdrom], "(not present)"); - else - sprintf (buffer[2+cdrom], "(%s on ata%d) %s, %s", - device&1?"slave":"master", device/2, cdromop.Opath->getptr (), - (cdromop.Ostatus->get () == BX_INSERTED)? "inserted" : "ejected"); - } - - snprintf (buf, size, format, buffer[0], buffer[1], buffer[2], - buffer[3], buffer[4], buffer[5], - /* ips->get (), */ - SIM->get_param_num (BXP_VGA_UPDATE_INTERVAL)->get (), - SIM->get_param_num (BXP_MOUSE_ENABLED)->get () ? "enabled" : "disabled", - SIM->get_param_num (BXP_KBD_PASTE_DELAY)->get (), - SIM->get_param_string (BXP_USER_SHORTCUT)->getptr ()); -} - -int do_menu (bx_id id) { - bx_list_c *menu = (bx_list_c *)SIM->get_param (id); - while (1) { - menu->get_choice()->set (0); - int status = menu->text_ask (stdin, stderr); - if (status < 0) return status; - bx_param_num_c *choice = menu->get_choice(); - if (choice->get () < 1) - return choice->get (); - else { - int index = choice->get () - 1; // choosing 1 means list[0] - bx_param_c *chosen = menu->get (index); - assert (chosen != NULL); - chosen->text_ask (stdin, stderr); - } - } -} - -void askparam (bx_id id) -{ - bx_param_c *param = SIM->get_param (id); - param->text_ask (stdin, stderr); -} - -int bx_config_interface (int menu) -{ - Bit32u choice; - while (1) { - switch (menu) - { - case BX_CI_INIT: - bx_config_interface_init (); - return 0; - case BX_CI_START_SIMULATION: { - SIM->begin_simulation (bx_startup_flags.argc, bx_startup_flags.argv); - // we don't expect it to return, but if it does, quit - SIM->quit_sim(1); - break; - } - case BX_CI_START_MENU: - { - Bit32u default_choice; - switch (SIM->get_param_enum(BXP_BOCHS_START)->get ()) { - case BX_LOAD_START: - default_choice = 2; break; - case BX_EDIT_START: - default_choice = 3; break; - default: - default_choice = 5; break; - } - - if (ask_uint (startup_menu_prompt, 1, 6, default_choice, &choice, 10) < 0) return -1; - switch (choice) { - case 1: - fprintf (stderr, "I reset all options back to their factory defaults.\n\n"); - SIM->reset_all_param (); - SIM->get_param_enum(BXP_BOCHS_START)->set(BX_EDIT_START); - break; - case 2: - // Before reading a new configuration, reset every option to its - // original state. - SIM->reset_all_param (); - if (bx_read_rc (NULL) >= 0) - SIM->get_param_enum(BXP_BOCHS_START)->set(BX_RUN_START); - break; - case 3: - bx_config_interface (BX_CI_START_OPTS); - SIM->get_param_enum(BXP_BOCHS_START)->set(BX_RUN_START); - break; - case 4: bx_write_rc (NULL); break; - case 5: bx_config_interface (BX_CI_START_SIMULATION); break; - case 6: SIM->quit_sim (1); return -1; - default: BAD_OPTION(menu, choice); - } - } - break; - case BX_CI_START_OPTS: - { - char prompt[CI_PATH_LENGTH]; - char oldpath[CI_PATH_LENGTH]; - char olddebuggerpath[CI_PATH_LENGTH]; - char oldprefix[CI_PATH_LENGTH]; - int retval; - - retval = SIM->get_log_file (oldpath, CI_PATH_LENGTH); - assert (retval >= 0); - double_percent(oldpath,CI_PATH_LENGTH); - retval = SIM->get_log_prefix (oldprefix, CI_PATH_LENGTH); - assert (retval >= 0); - double_percent(oldprefix,CI_PATH_LENGTH); - retval = SIM->get_debugger_log_file (olddebuggerpath, CI_PATH_LENGTH); - assert (retval >= 0); - double_percent(olddebuggerpath,CI_PATH_LENGTH); - - sprintf (prompt, startup_options_prompt, oldpath, oldprefix, olddebuggerpath); - if (ask_uint (prompt, 0, 13, 0, &choice, 10) < 0) return -1; - switch (choice) { - case 0: return 0; - case 1: askparam (BXP_LOG_FILENAME); break; - case 2: askparam (BXP_LOG_PREFIX); break; - case 3: askparam (BXP_DEBUGGER_LOG_FILENAME); break; - case 4: bx_log_options (0); break; - case 5: bx_log_options (1); break; - case 6: do_menu (BXP_MENU_MEMORY); break; - case 7: do_menu (BXP_MENU_INTERFACE); break; - case 8: do_menu (BXP_MENU_DISK); break; - case 9: do_menu (BXP_MENU_SERIAL_PARALLEL); break; - case 10: do_menu (BXP_SB16); break; - case 11: do_menu (BXP_NE2K); break; - case 12: do_menu (BXP_MENU_KEYBOARD); break; - case 13: do_menu (BXP_MENU_MISC); break; - default: BAD_OPTION(menu, choice); - } - } - break; - case BX_CI_RUNTIME: - char prompt[1024]; - bx_floppy_options floppyop; - bx_atadevice_options cdromop; - build_runtime_options_prompt (runtime_menu_prompt, prompt, 1024); - if (ask_uint (prompt, 1, 16, 15, &choice, 10) < 0) return -1; - switch (choice) { - case 1: - SIM->get_floppy_options (0, &floppyop); - if (floppyop.Odevtype->get () != BX_FLOPPY_NONE) do_menu (BXP_FLOPPYA); - break; - case 2: - SIM->get_floppy_options (1, &floppyop); - if (floppyop.Odevtype->get () != BX_FLOPPY_NONE) do_menu (BXP_FLOPPYB); - break; - case 3: - case 4: - case 5: - case 6: - int device; - if (SIM->get_cdrom_options (choice - 3, &cdromop, &device) && cdromop.Opresent->get ()) { - // disable type selection - SIM->get_param((bx_id)(BXP_ATA0_MASTER_TYPE + device))->set_enabled(0); - SIM->get_param((bx_id)(BXP_ATA0_MASTER_MODEL + device))->set_enabled(0); - SIM->get_param((bx_id)(BXP_ATA0_MASTER_BIOSDETECT + device))->set_enabled(0); - do_menu ((bx_id)(BXP_ATA0_MASTER + device)); - } - break; - case 7: // not implemented yet because I would have to mess with - // resetting timers and pits and everything on the fly. - // askparam (BXP_IPS); - break; - case 8: bx_log_options (0); break; - case 9: bx_log_options (1); break; - case 10: askparam (BXP_VGA_UPDATE_INTERVAL); break; - case 11: askparam (BXP_MOUSE_ENABLED); break; - case 12: askparam (BXP_KBD_PASTE_DELAY); break; - case 13: askparam (BXP_USER_SHORTCUT); break; - case 14: NOT_IMPLEMENTED (choice); break; - case 15: fprintf (stderr, "Continuing simulation\n"); return 0; - case 16: - fprintf (stderr, "You chose quit on the configuration interface.\n"); - SIM->quit_sim (1); - return -1; - default: fprintf (stderr, "Menu choice %d not implemented.\n", choice); - } - break; - default: - fprintf (stderr, "Unknown config interface menu type.\n"); - assert (menu >=0 && menu < BX_CI_N_MENUS); - } - } -} - -static void bx_print_log_action_table () -{ - // just try to print all the prefixes first. - fprintf (stderr, "Current log settings:\n"); - fprintf (stderr, " Debug Info Error Panic Pass\n"); - fprintf (stderr, "ID Device Action Action Action Action Action\n"); - fprintf (stderr, "---- --------- --------- --------- ---------- ---------- ----------\n"); - int i, j, imax=SIM->get_n_log_modules (); - for (i=0; iget_prefix(i), "[ ]")) { - fprintf (stderr, "%3d. %s ", i, SIM->get_prefix (i)); - for (j=0; jget_max_log_level (); j++) { - fprintf (stderr, "%10s ", SIM->get_action_name (SIM->get_log_action (i, j))); - } - fprintf (stderr, "\n"); - } - } -} - -static char *log_options_prompt1 = "Enter the ID of the device to edit, or -1 to return: [-1] "; -static char *log_level_choices[] = { "ignore", "report", "ask", "fatal", "no change" }; -static int log_level_n_choices_normal = 4; - -void bx_log_options (int individual) -{ - if (individual) { - int done = 0; - while (!done) { - bx_print_log_action_table (); - Bit32s id, level, action; - Bit32s maxid = SIM->get_n_log_modules (); - if (ask_int (log_options_prompt1, -1, maxid-1, -1, &id) < 0) - return; - if (id < 0) return; - fprintf (stderr, "Editing log options for the device %s\n", SIM->get_prefix (id)); - for (level=0; levelget_max_log_level (); level++) { - char prompt[1024]; - int default_action = SIM->get_log_action (id, level); - sprintf (prompt, "Enter action for %s event: [%s] ", SIM->get_log_level_name (level), SIM->get_action_name(default_action)); - // don't show the no change choice (choices=3) - if (ask_menu (prompt, log_level_n_choices_normal, log_level_choices, default_action, &action)<0) - return; - SIM->set_log_action (id, level, action); - } - } - } else { - // provide an easy way to set log options for all devices at once - bx_print_log_action_table (); - for (int level=0; levelget_max_log_level (); level++) { - char prompt[1024]; - int action, default_action = 3; // default to no change - sprintf (prompt, "Enter action for %s event on all devices: [no change] ", SIM->get_log_level_name (level)); - // do show the no change choice (choices=4) - if (ask_menu (prompt, log_level_n_choices_normal+1, log_level_choices, default_action, &action)<0) - return; - if (action < 3) { - SIM->set_default_log_action (level, action); - SIM->set_log_action (-1, level, action); - } - } - } -} - -int bx_read_rc (char *rc) -{ - if (rc && SIM->read_rc (rc) >= 0) return 0; - char oldrc[CI_PATH_LENGTH]; - if (SIM->get_default_rc (oldrc, CI_PATH_LENGTH) < 0) - strcpy (oldrc, "none"); - char newrc[CI_PATH_LENGTH]; - while (1) { - if (ask_string ("\nWhat is the configuration file name?\nTo cancel, type 'none'. [%s] ", oldrc, newrc) < 0) return -1; - if (!strcmp (newrc, "none")) return -1; - if (SIM->read_rc (newrc) >= 0) return 0; - fprintf (stderr, "The file '%s' could not be found.\n", newrc); - } -} - -int bx_write_rc (char *rc) -{ - char oldrc[CI_PATH_LENGTH], newrc[CI_PATH_LENGTH]; - if (rc == NULL) { - if (SIM->get_default_rc (oldrc, CI_PATH_LENGTH) < 0) - strcpy (oldrc, "none"); - } else { - strncpy (oldrc, rc, CI_PATH_LENGTH); - } - while (1) { - if (ask_string ("Save configuration to what file? To cancel, type 'none'.\n[%s] ", oldrc, newrc) < 0) return -1; - if (!strcmp (newrc, "none")) return 0; - // try with overwrite off first - int status = SIM->write_rc (newrc, 0); - if (status >= 0) { - fprintf (stderr, "Wrote configuration to '%s'.\n", newrc); - return 0; - } else if (status == -2) { - // return code -2 indicates the file already exists, and overwrite - // confirmation is required. - Bit32u overwrite = 0; - char prompt[256]; - sprintf (prompt, "Configuration file '%s' already exists. Overwrite it? [no] ", newrc); - if (ask_yn (prompt, 0, &overwrite) < 0) return -1; - if (!overwrite) continue; // if "no", start loop over, asking for a different file - // they confirmed, so try again with overwrite bit set - if (SIM->write_rc (newrc, 1) >= 0) { - fprintf (stderr, "Overwriting existing configuration '%s'.\n", newrc); - return 0; - } else { - fprintf (stderr, "Write failed to '%s'.\n", newrc); - } - } - } -} - -char *log_action_ask_choices[] = { "cont", "alwayscont", "die", "abort", "debug" }; -int log_action_n_choices = 4 + (BX_DEBUGGER?1:0); - -BxEvent * -config_interface_notify_callback (void *unused, BxEvent *event) -{ -#ifdef WIN32 - int opts; - bx_param_c *param; - bx_param_string_c *sparam; -#endif - event->retcode = -1; - switch (event->type) - { - case BX_SYNC_EVT_TICK: - event->retcode = 0; - return event; - case BX_SYNC_EVT_ASK_PARAM: -#ifdef WIN32 - param = event->u.param.param; - if (param->get_type() == BXT_PARAM_STRING) { - sparam = (bx_param_string_c *)param; - opts = sparam->get_options()->get(); - if (opts & sparam->IS_FILENAME) { - if (param->get_id() == BXP_NULL) { - event->retcode = AskFilename(GetBochsWindow(), (bx_param_filename_c *)sparam); - } else { - event->retcode = FloppyDialog((bx_param_filename_c *)sparam); - } - return event; - } else { - event->retcode = AskString(sparam); - return event; - } - } -#endif - event->u.param.param->text_ask (stdin, stderr); - return event; - case BX_SYNC_EVT_LOG_ASK: - { -#ifdef WIN32 - LogAskDialog(event); -#else - int level = event->u.logmsg.level; - fprintf (stderr, "========================================================================\n"); - fprintf (stderr, "Event type: %s\n", SIM->get_log_level_name (level)); - fprintf (stderr, "Device: %s\n", event->u.logmsg.prefix); - fprintf (stderr, "Message: %s\n\n", event->u.logmsg.msg); - fprintf (stderr, "A %s has occurred. Do you want to:\n", SIM->get_log_level_name (level)); - fprintf (stderr, " cont - continue execution\n"); - fprintf (stderr, " alwayscont - continue execution, and don't ask again.\n"); - fprintf (stderr, " This affects only %s events from device %s\n", SIM->get_log_level_name (level), event->u.logmsg.prefix); - fprintf (stderr, " die - stop execution now\n"); - fprintf (stderr, " abort - dump core %s\n", - BX_HAVE_ABORT ? "" : "(Disabled)"); -#if BX_DEBUGGER - fprintf (stderr, " debug - continue and return to bochs debugger\n"); -#endif - int choice; -ask: - if (ask_menu ("Choose one of the actions above: [%s] ", - log_action_n_choices, log_action_ask_choices, 2, &choice) < 0) - event->retcode = -1; - // return 0 for continue, 1 for alwayscontinue, 2 for die, 3 for debug. - if (!BX_HAVE_ABORT && choice==BX_LOG_ASK_CHOICE_DUMP_CORE) goto ask; - fflush(stdout); - fflush(stderr); - event->retcode = choice; -#endif - } - return event; - case BX_ASYNC_EVT_REFRESH: - case BX_ASYNC_EVT_DBG_MSG: - // The text mode interface does not use these events, so just ignore - // them. - return event; - default: - fprintf (stderr, "Control panel: notify callback called with event type %04x\n", event->type); - return event; - } - assert (0); // switch statement should return -} - -void bx_config_interface_init () { - //fprintf (stderr, "bx_config_interface_init()\n"); - SIM->set_notify_callback (config_interface_notify_callback, NULL); -} - -///////////////////////////////////////////////////////////////////// -// implement the text_* methods for bx_param types. - -void -bx_param_num_c::text_print (FILE *fp) -{ - //fprintf (fp, "number parameter, id=%u, name=%s\n", get_id (), get_name ()); - //fprintf (fp, "value=%u\n", get ()); - if (get_format ()) { - fprintf (fp, get_format (), get ()); - } else { - char *format = "%s: %d"; - assert (base==10 || base==16); - if (base==16) format = "%s: 0x%x"; - fprintf (fp, format, get_name (), get ()); - } -} - -void -bx_param_bool_c::text_print (FILE *fp) -{ - if (get_format ()) { - fprintf (fp, get_format (), get () ? "yes" : "no"); - } else { - char *format = "%s: %s"; - fprintf (fp, format, get_name (), get () ? "yes" : "no"); - } -} - -void -bx_param_enum_c::text_print (FILE *fp) -{ - int n = get (); - assert (n >= min && n <= max); - char *choice = choices[n - min]; - if (get_format ()) { - fprintf (fp, get_format (), choice); - } else { - char *format = "%s: %s"; - fprintf (fp, format, get_name (), choice); - } -} - -void -bx_param_string_c::text_print (FILE *fp) -{ - char *value = getptr (); - int opts = options->get (); - if (opts & RAW_BYTES) { - char buffer[1024]; - buffer[0] = 0; - char sep_string[2]; - sep_string[0] = separator; - sep_string[1] = 0; - for (int i=0; i0)?sep_string : "", (unsigned int)0xff&val[i]); - strncat (buffer, eachbyte, sizeof(buffer)); - } - if (strlen (buffer) > sizeof(buffer)-4) { - assert (0); // raw byte print buffer is probably overflowing. increase the max or make it dynamic - } - value = buffer; - } - if (get_format ()) { - fprintf (fp, get_format (), value); - } else { - fprintf (fp, "%s: %s", get_name (), value); - } -} - -void -bx_list_c::text_print (FILE *fp) -{ - //fprintf (fp, "This is a list.\n"); - //fprintf (fp, "title=%s\n", title->getptr ()); - fprintf (fp, "%s: ", get_name ()); - /* - fprintf (fp, "options=%s%s%s\n", - (options->get () == 0) ? "none" : "", - (options->get () & SHOW_PARENT) ? "SHOW_PARENT " : "", - (options->get () & SERIES_ASK) ? "SERIES_ASK " : ""); - */ - for (int i=0; iget_enabled ()) { - if ((i>0) && (options->get () & SERIES_ASK)) - fprintf (fp, ", "); - list[i]->text_print (fp); - if (!(options->get () & SERIES_ASK)) - fprintf (fp, "\n"); - } - } -} - -int -bx_param_num_c::text_ask (FILE *fpin, FILE *fpout) -{ - fprintf (fpout, "\n"); - int status; - char *prompt = get_ask_format (); - if (prompt == NULL) { - // default prompt, if they didn't set an ask format string - text_print (fpout); - fprintf (fpout, "\n"); - prompt = "Enter new value: [%d] "; - if (base==16) - prompt = "Enter new value in hex: [%x] "; - } - Bit32u n = get (); - status = ask_uint (prompt, min, max, n, &n, base); - if (status < 0) return status; - set (n); - return 0; -} - -int -bx_param_bool_c::text_ask (FILE *fpin, FILE *fpout) -{ - fprintf (fpout, "\n"); - int status; - char *prompt = get_ask_format (); - char buffer[512]; - if (prompt == NULL) { - // default prompt, if they didn't set an ask format string - sprintf (buffer, "%s? [%%s] ", get_name ()); - prompt = buffer; - } - Bit32u n = get (); - status = ask_yn (prompt, n, &n); - if (status < 0) return status; - set (n); - return 0; -} - -int -bx_param_enum_c::text_ask (FILE *fpin, FILE *fpout) -{ - fprintf (fpout, "\n"); - char *prompt = get_ask_format (); - if (prompt == NULL) { - // default prompt, if they didn't set an ask format string - fprintf (fpout, "%s = ", get_name ()); - text_print (fpout); - fprintf (fpout, "\n"); - prompt = "Enter new value: [%s] "; - } - Bit32s n = (Bit32s)(get () - min); - int status = ask_menu (prompt, (max-min+1), choices, n, &n); - if (status < 0) return status; - n += (Bit32s)min; - set (n); - return 0; -} - -int parse_raw_bytes (char *dest, char *src, int destsize, char separator) -{ - //printf ("parsing src='%s'\n", src); - int i; - unsigned int n; - for (i=0; iget (); - char buffer2[1024]; - strcpy (buffer2, buffer); - if (status == 1 && opts & RAW_BYTES) { - // copy raw hex into buffer - status = parse_raw_bytes (buffer, buffer2, maxsize, separator); - if (status < 0) { - fprintf (fpout, "Illegal raw byte format. I expected something like 3A%c03%c12%c...\n", separator, separator, separator); - continue; - } - } - if (!equals (buffer)) - set (buffer); - return 0; - } -} - -int -bx_list_c::text_ask (FILE *fpin, FILE *fpout) -{ - char *my_title = title->getptr (); - fprintf (fpout, "\n"); - int i, imax = strlen (my_title); - for (i=0; iget ()); - if (options->get () & SERIES_ASK) { - for (int i=0; iget_enabled ()) - list[i]->text_ask (fpin, fpout); - } - } else { - if (options->get () & SHOW_PARENT) - fprintf (fpout, "0. Return to previous menu\n"); - for (int i=0; iget_enabled ()) { - list[i]->text_print (fpout); - fprintf (fpout, "\n"); - } else - fprintf (fpout, "(disabled)\n"); - } - fprintf (fpout, "\n"); - Bit32u n = choice->get (); - int min = (options->get () & SHOW_PARENT) ? 0 : 1; - int max = size; - int status = ask_uint ("Please choose one: [%d] ", min, max, n, &n, 10); - if (status < 0) return status; - choice->set (n); - } - return 0; -} - -static int ci_callback (void *userdata, ci_command_t command) -{ - switch (command) - { - case CI_START: - //fprintf (stderr, "textconfig.cc: start\n"); - bx_config_interface_init (); - if (SIM->get_param_enum(BXP_BOCHS_START)->get () == BX_QUICK_START) - bx_config_interface (BX_CI_START_SIMULATION); - else { - if (!SIM->test_for_text_console ()) - return CI_ERR_NO_TEXT_CONSOLE; - bx_config_interface (BX_CI_START_MENU); - } - break; - case CI_RUNTIME_CONFIG: - bx_config_interface (BX_CI_RUNTIME); - break; - case CI_SHUTDOWN: - //fprintf (stderr, "textconfig.cc: shutdown\n"); - break; - } - return 0; -} - -// if I can make things compile without this module linked in, then -// this file can become a plugin too. -int init_text_config_interface () -{ - //fprintf (stderr, "plugin_init for textconfig.cc\n"); - SIM->register_configuration_interface ("textconfig", ci_callback, NULL); - return 0; // success -} diff --git a/tools/ioemu/gui/textconfig.h b/tools/ioemu/gui/textconfig.h deleted file mode 100644 index 01687ca269..0000000000 --- a/tools/ioemu/gui/textconfig.h +++ /dev/null @@ -1,19 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: textconfig.h,v 1.1 2002/10/29 20:16:04 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -enum { - BX_CI_INIT, - BX_CI_START_MENU, - BX_CI_START_OPTS, - BX_CI_START_OPTS_MEM, - BX_CI_START_OPTS_INTERFACE, - BX_CI_START_OPTS_DISK, - BX_CI_START_OPTS_SOUND, - BX_CI_START_OPTS_MISC, - BX_CI_START_SIMULATION, - BX_CI_RUNTIME, - BX_CI_N_MENUS -}; - -int init_text_config_interface (); diff --git a/tools/ioemu/gui/x.cc b/tools/ioemu/gui/x.cc deleted file mode 100644 index 5d1cae917a..0000000000 --- a/tools/ioemu/gui/x.cc +++ /dev/null @@ -1,1848 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: x.cc,v 1.76 2003/08/11 19:27:57 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -#define XK_PUBLISHING -#define XK_TECHNICAL - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_WITH_X11 - -extern "C" { -#include -#include -#include -#include -#include -#if BX_HAVE_XPM_H -#include -#endif -} - -#if BX_HAVE_XPM_H -#include "icon_bochs.xpm" -#else -#include "icon_bochs.h" -#endif - -#include "font/vga.bitmap.h" - -class bx_x_gui_c : public bx_gui_c { -public: - bx_x_gui_c (void); - DECLARE_GUI_VIRTUAL_METHODS() -#if BX_USE_IDLE_HACK - virtual void sim_is_idle(void); -#endif -}; - -// declare one instance of the gui object and call macro to insert the -// plugin code -static bx_x_gui_c *theGui = NULL; -IMPLEMENT_GUI_PLUGIN_CODE(x) - -#define LOG_THIS theGui-> - -#define MAX_MAPPED_STRING_LENGTH 10 - -/* These are used as arguments to nearly every Xlib routine, so it saves - * routine arguments to declare them global. If there were - * additional source files, they would be declared extern there. */ -Display *bx_x_display; -int bx_x_screen_num; -static Colormap default_cmap; -static unsigned long white_pixel=0, black_pixel=0; - -static char *progname; /* name this program was invoked by */ - -static unsigned int text_rows=25, text_cols=80; -static Bit8u h_panning = 0, v_panning = 0; - -static Window win; -static GC gc, gc_inv, gc_headerbar, gc_headerbar_inv; -static unsigned font_width, font_height; -static unsigned dimension_x=0, dimension_y=0; -static unsigned vga_bpp=8; - -static XImage *ximage = NULL; -static unsigned imDepth, imWide, imBPP; - -// current cursor coordinates -static int prev_x=-1, prev_y=-1; -static int current_x=-1, current_y=-1; -static unsigned mouse_button_state = 0; - -static unsigned prev_cursor_x=0; -static unsigned prev_cursor_y=0; - -static int warp_home_x = 200; -static int warp_home_y = 200; -static int mouse_enable_x = 0; -static int mouse_enable_y = 0; -static int warp_dx = 0; -static int warp_dy = 0; - -static void warp_cursor(int dx, int dy); -static void disable_cursor(); -static void enable_cursor(); - -static Bit32u convertStringToXKeysym (const char *string); - -static bx_bool x_init_done = false; - -static Pixmap vgafont[256]; - -struct { - Pixmap bmap; - unsigned xdim; - unsigned ydim; - } bx_bitmaps[BX_MAX_PIXMAPS]; -unsigned bx_bitmap_entries = 0; - -static struct { - Pixmap bitmap; - unsigned xdim; - unsigned ydim; - unsigned xorigin; - unsigned yorigin; - unsigned alignment; - void (*f)(void); - } bx_headerbar_entry[BX_MAX_HEADERBAR_ENTRIES]; -static unsigned bx_headerbar_y = 0; -static unsigned bx_headerbar_entries = 0; -static unsigned bx_bitmap_left_xorigin = 0; // pixels from left -static unsigned bx_bitmap_right_xorigin = 0; // pixels from right - -static void headerbar_click(int x, int y); -static void send_keyboard_mouse_status(void); - - - - -Bit32u ascii_to_key_event[0x5f] = { - // !"#$%&' - BX_KEY_SPACE, - BX_KEY_1, - BX_KEY_SINGLE_QUOTE, - BX_KEY_3, - BX_KEY_4, - BX_KEY_5, - BX_KEY_7, - BX_KEY_SINGLE_QUOTE, - - // ()*+,-./ - BX_KEY_9, - BX_KEY_0, - BX_KEY_8, - BX_KEY_EQUALS, - BX_KEY_COMMA, - BX_KEY_MINUS, - BX_KEY_PERIOD, - BX_KEY_SLASH, - - // 01234567 - BX_KEY_0, - BX_KEY_1, - BX_KEY_2, - BX_KEY_3, - BX_KEY_4, - BX_KEY_5, - BX_KEY_6, - BX_KEY_7, - - // 89:;<=>? - BX_KEY_8, - BX_KEY_9, - BX_KEY_SEMICOLON, - BX_KEY_SEMICOLON, - BX_KEY_COMMA, - BX_KEY_EQUALS, - BX_KEY_PERIOD, - BX_KEY_SLASH, - - // @ABCDEFG - BX_KEY_2, - BX_KEY_A, - BX_KEY_B, - BX_KEY_C, - BX_KEY_D, - BX_KEY_E, - BX_KEY_F, - BX_KEY_G, - - - // HIJKLMNO - BX_KEY_H, - BX_KEY_I, - BX_KEY_J, - BX_KEY_K, - BX_KEY_L, - BX_KEY_M, - BX_KEY_N, - BX_KEY_O, - - - // PQRSTUVW - BX_KEY_P, - BX_KEY_Q, - BX_KEY_R, - BX_KEY_S, - BX_KEY_T, - BX_KEY_U, - BX_KEY_V, - BX_KEY_W, - - // XYZ[\]^_ - BX_KEY_X, - BX_KEY_Y, - BX_KEY_Z, - BX_KEY_LEFT_BRACKET, - BX_KEY_BACKSLASH, - BX_KEY_RIGHT_BRACKET, - BX_KEY_6, - BX_KEY_MINUS, - - // `abcdefg - BX_KEY_GRAVE, - BX_KEY_A, - BX_KEY_B, - BX_KEY_C, - BX_KEY_D, - BX_KEY_E, - BX_KEY_F, - BX_KEY_G, - - // hijklmno - BX_KEY_H, - BX_KEY_I, - BX_KEY_J, - BX_KEY_K, - BX_KEY_L, - BX_KEY_M, - BX_KEY_N, - BX_KEY_O, - - // pqrstuvw - BX_KEY_P, - BX_KEY_Q, - BX_KEY_R, - BX_KEY_S, - BX_KEY_T, - BX_KEY_U, - BX_KEY_V, - BX_KEY_W, - - // xyz{|}~ - BX_KEY_X, - BX_KEY_Y, - BX_KEY_Z, - BX_KEY_LEFT_BRACKET, - BX_KEY_BACKSLASH, - BX_KEY_RIGHT_BRACKET, - BX_KEY_GRAVE - }; - -extern Bit8u graphics_snapshot[32 * 1024]; - - -static void create_internal_vga_font(void); -static void xkeypress(KeySym keysym, int press_release); -// extern "C" void select_visual(void); - -#define ROUNDUP(nbytes, pad) ((((nbytes) + ((pad)-1)) / (pad)) * ((pad)>>3)) - - -#define MAX_VGA_COLORS 256 - -unsigned long col_vals[MAX_VGA_COLORS]; // 256 VGA colors -unsigned curr_foreground, curr_background; - -static unsigned x_tilesize, y_tilesize; - - -// Try to allocate NCOLORS at once in the colormap provided. If it can -// be done, return true. If not, return false. (In either case, free -// up the color cells so that we don't add to the problem!) This is used -// to determine whether Bochs should use a private colormap even when the -// user did not specify it. -static bx_bool -test_alloc_colors (Colormap cmap, Bit32u n_tries) { - XColor color; - unsigned long pixel[MAX_VGA_COLORS]; - bx_bool pixel_valid[MAX_VGA_COLORS]; - Bit32u n_allocated = 0; - Bit32u i; - color.flags = DoRed | DoGreen | DoBlue; - for (i=0; iget ()) { - default_cmap = DefaultColormap(bx_x_display, bx_x_screen_num); - // try to use default colormap. If not enough colors are available, - // then switch to private colormap despite the user setting. There - // are too many cases when no colors are available and Bochs simply - // draws everything in black on black. - if (!test_alloc_colors (default_cmap, 16)) { - BX_ERROR (("I can't even allocate 16 colors! Switching to a private colormap")); - bx_options.Oprivate_colormap->set (1); - } - col_vals[0] = BlackPixel(bx_x_display, bx_x_screen_num); - col_vals[15] = WhitePixel(bx_x_display, bx_x_screen_num); - for (i = 1; i < MAX_VGA_COLORS; i++) { - if (i==15) continue; - col_vals[i] = col_vals[0]; - } - } - - if (bx_options.Oprivate_colormap->get ()) { - default_cmap = XCreateColormap(bx_x_display, DefaultRootWindow(bx_x_display), - default_visual, AllocNone); - if (XAllocColorCells(bx_x_display, default_cmap, False, - plane_masks_return, 0, col_vals, MAX_VGA_COLORS) == 0) { - BX_PANIC(("XAllocColorCells returns error. Maybe your screen does not support a private colormap?")); - } - - win_attr.colormap = default_cmap; - XChangeWindowAttributes(bx_x_display, win, CWColormap, &win_attr); - - color.flags = DoRed | DoGreen | DoBlue; - - for (i=0; i < MAX_VGA_COLORS; i++) { - color.pixel = i; - if (i==15) { - color.red = 0xffff; - color.green = 0xffff; - color.blue = 0xffff; - } - else { - color.red = 0; - color.green = 0; - color.blue = 0; - } - XStoreColor(bx_x_display, default_cmap, &color); - } - } - - // convenience variables which hold the black & white color indeces - black_pixel = col_vals[0]; - white_pixel = col_vals[15]; - - BX_INFO(("font %u wide x %u high, display depth = %d", - (unsigned) font_width, (unsigned) font_height, default_depth)); - - //select_visual(); - - - /* Get available icon sizes from Window manager */ - -#if BX_HAVE_XPM_H - /* Create pixmap from XPM for icon */ - XCreatePixmapFromData(bx_x_display, win, icon_bochs_xpm, &icon_pixmap, &icon_mask, NULL); -#else - /* Create pixmap of depth 1 (bitmap) for icon */ - icon_pixmap = XCreateBitmapFromData(bx_x_display, win, - (char *) bochs_icon_bits, bochs_icon_width, bochs_icon_height); -#endif - - /* Set size hints for window manager. The window manager may - * override these settings. Note that in a real - * application if size or position were set by the user - * the flags would be UPosition and USize, and these would - * override the window manager's preferences for this window. */ - /* x, y, width, and height hints are now taken from - * the actual settings of the window when mapped. Note - * that PPosition and PSize must be specified anyway. */ - - size_hints.flags = PPosition | PSize | PMinSize | PMaxSize; - size_hints.max_width = size_hints.min_width = dimension_x; - size_hints.max_height = size_hints.min_height = dimension_y; - - { - XWMHints wm_hints; - XClassHint class_hints; - - /* format of the window name and icon name - * arguments has changed in R4 */ - XTextProperty windowName, iconName; - - /* These calls store window_name and icon_name into - * XTextProperty structures and set their other - * fields properly. */ - if (XStringListToTextProperty(&window_name, 1, &windowName) == 0) { - BX_PANIC(("%s: structure allocation for windowName failed.", - progname)); - } - - if (XStringListToTextProperty(&icon_name, 1, &iconName) == 0) { - BX_PANIC(("%s: structure allocation for iconName failed.", - progname)); - } - - wm_hints.initial_state = NormalState; - wm_hints.input = True; - wm_hints.icon_pixmap = icon_pixmap; -#if BX_HAVE_XPM_H - wm_hints.icon_mask = icon_mask; - wm_hints.flags = StateHint | IconPixmapHint | IconMaskHint | InputHint; -#else - wm_hints.flags = StateHint | IconPixmapHint | InputHint; -#endif - class_hints.res_name = progname; - class_hints.res_class = "Bochs"; - - XSetWMProperties(bx_x_display, win, &windowName, &iconName, - argv, argc, &size_hints, &wm_hints, - &class_hints); - } - - /* Select event types wanted */ - XSelectInput(bx_x_display, win, ExposureMask | KeyPressMask | KeyReleaseMask | - ButtonPressMask | ButtonReleaseMask | StructureNotifyMask | PointerMotionMask | - EnterWindowMask | LeaveWindowMask ); - - - /* Create default Graphics Context */ - gc = XCreateGC(bx_x_display, win, valuemask, &values); - gc_inv = XCreateGC(bx_x_display, win, valuemask, &values); - gc_headerbar = XCreateGC(bx_x_display, win, valuemask, &values); - gc_headerbar_inv = XCreateGC(bx_x_display, win, valuemask, &values); - - XSetState(bx_x_display, gc, white_pixel, black_pixel, GXcopy,AllPlanes); - - XSetState(bx_x_display, gc_inv, black_pixel, white_pixel, GXinvert,AllPlanes); - - XSetState(bx_x_display, gc_headerbar, black_pixel, white_pixel, GXcopy,AllPlanes); - - XSetState(bx_x_display, gc_headerbar_inv, white_pixel, black_pixel, GXcopy,AllPlanes); - - - /* Display window */ - XMapWindow(bx_x_display, win); - XSync(bx_x_display, /* no discard */ 0); - - BX_DEBUG(("waiting for MapNotify")); - while (1) { - XNextEvent(bx_x_display, &report); - if (report.type == MapNotify) break; - } - BX_DEBUG(("MapNotify found.")); - - // Create the VGA font - create_internal_vga_font(); - - -{ - char *imagedata; - - ximage = XCreateImage(bx_x_display, default_visual, - default_depth, // depth of image (bitplanes) - ZPixmap, - 0, // offset - NULL, // malloc() space after - x_tilesize, y_tilesize, // x & y size of image - 32, // # bits of padding - 0 ); // bytes_per_line, let X11 calculate - if (!ximage) - BX_PANIC(("vga: couldn't XCreateImage()")); - - imDepth = default_depth; - imWide = ximage->bytes_per_line; - imBPP = ximage->bits_per_pixel; - - imagedata = (char *) malloc( (size_t) (ximage->bytes_per_line * y_tilesize) ); - if (!imagedata) BX_PANIC(("imagedata: malloc returned error")); - - ximage->data = imagedata; - - if (imBPP < imDepth) { - BX_PANIC(("vga_x: bits_per_pixel < depth ?")); - } - - x_init_done = true; - -} - - curr_background = 0; - XSetBackground(bx_x_display, gc, col_vals[curr_background]); - curr_foreground = 1; - XSetForeground(bx_x_display, gc, col_vals[curr_foreground]); - //XGrabPointer( bx_x_display, win, True, 0, GrabModeAsync, GrabModeAsync, - // win, None, CurrentTime ); - - - XFlush(bx_x_display); - - // loads keymap for x11 - if(bx_options.keyboard.OuseMapping->get()) { - bx_keymap.loadKeymap(convertStringToXKeysym); - } -} - - -// This is called whenever the mouse_enabled parameter changes. It -// can change because of a gui event such as clicking on the mouse-enable -// bitmap or pressing the middle button, or from the configuration interface. -// In all those cases, setting the parameter value will get you here. - void -bx_x_gui_c::mouse_enabled_changed_specific (bx_bool val) -{ - BX_DEBUG (("mouse_enabled=%d, x11 specific code", val?1:0)); - if (val) { - BX_INFO(("[x] Mouse on")); - mouse_enable_x = current_x; - mouse_enable_y = current_y; - disable_cursor(); - // Move the cursor to a 'safe' place - warp_cursor(warp_home_x-current_x, warp_home_y-current_y); - } else { - BX_INFO(("[x] Mouse off")); - enable_cursor(); - warp_cursor(mouse_enable_x-current_x, mouse_enable_y-current_y); - } -} - - void -create_internal_vga_font(void) -{ - // Default values - font_width=8; - font_height=16; - - for(int i=0; i<256; i++) { - vgafont[i]=XCreateBitmapFromData(bx_x_display, win, (const char*)bx_vgafont[i].data, - font_width, font_height); - if(vgafont[i] == None) - BX_PANIC(("Can't create vga font [%d]", i)); - } -} - - void -bx_x_gui_c::handle_events(void) -{ - XEvent report; - XKeyEvent *key_event; - KeySym keysym; - XComposeStatus compose; - char buffer[MAX_MAPPED_STRING_LENGTH]; - int bufsize = MAX_MAPPED_STRING_LENGTH; - int charcount; - bx_bool mouse_update; - int y, height; - - - XPointerMovedEvent *pointer_event; - XEnterWindowEvent *enter_event; - XLeaveWindowEvent *leave_event; - XButtonEvent *button_event; - XExposeEvent *expose_event; - - - //current_x = -1; - //current_y = -1; - mouse_update = 0; - - while (XPending(bx_x_display) > 0) { - XNextEvent(bx_x_display, &report); - switch (report.type) { - - case Expose: - expose_event = &report.xexpose; - /* Adjust y, and reduce height if it overlaps headerbar. */ - y = expose_event->y - BX_HEADER_BAR_Y; - height = expose_event->height; - if (y < 0) { - height += y; - y = 0; - } - - DEV_vga_redraw_area( - (unsigned) expose_event->x, - y, - (unsigned) expose_event->width, - height); - - /* Always draw headerbar, even if not touched by expose event. - * As a small optimization, only do it on last contigous expose. - */ - if (expose_event->count == 0) { - show_headerbar(); - } - break; - - case ConfigureNotify: - BX_DEBUG(("ConfigureNotify Xevent")); - /* FIXME: It's not clear why we have to show the headerbar here. - * This should be forced by the following expose events. - */ - show_headerbar(); - break; - - case ButtonPress: - button_event = (XButtonEvent *) &report; - BX_DEBUG(("xxx: buttonpress")); - if (button_event->y < BX_HEADER_BAR_Y) { - BX_DEBUG(("xxx: in headerbar")); - if (mouse_update) { - BX_DEBUG(("xxx: mouse_update=1")); - send_keyboard_mouse_status(); - mouse_update = 0; - } - prev_x = current_x = -1; - prev_y = current_y = -1; - headerbar_click(button_event->x, button_event->y); - break; - } - current_x = button_event->x; - current_y = button_event->y; - mouse_update = 1; - BX_DEBUG(("xxx: x,y=(%d,%d)", current_x, current_y)); - switch (button_event->button) { - case Button1: - BX_DEBUG(("xxx: button1")); - mouse_button_state |= 0x01; - send_keyboard_mouse_status(); - mouse_update = 0; - break; - case Button2: - BX_DEBUG(("XXX: button2")); - - // (mch) Hack for easier mouse handling (toggle mouse enable) - toggle_mouse_enable(); - - //mouse_button_state |= ; - //send_keyboard_mouse_status(); - //mouse_update = 0; - break; - case Button3: - BX_DEBUG(("xxx: button3")); - mouse_button_state |= 0x02; - send_keyboard_mouse_status(); - mouse_update = 0; - break; - } - break; - - case ButtonRelease: - button_event = (XButtonEvent *) &report; -//BX_INFO(("xxx: buttonrelease")); - if (button_event->y < BX_HEADER_BAR_Y) { -//BX_INFO(("xxx: in headerbar")); - if (mouse_update) { -//BX_INFO(("xxx: mouse_update=1")); - send_keyboard_mouse_status(); - mouse_update = 0; - } - prev_x = current_x = -1; - prev_y = current_y = -1; - // ignore, in headerbar area - break; - } - current_x = button_event->x; - current_y = button_event->y; - mouse_update = 1; -//BX_INFO(("xxx: x,y=(%d,%d)", current_x, current_y)); - switch (button_event->button) { - case Button1: -//BX_INFO(("xxx: button1")); - mouse_button_state &= ~0x01; - send_keyboard_mouse_status(); - mouse_update = 0; - break; - case Button2: -//BX_INFO(("xxx: button2")); - //mouse_button_state &= ~; - //send_keyboard_mouse_status(); - //mouse_update = 0; - break; - case Button3: -//BX_INFO(("xxx: button3")); - mouse_button_state &= ~0x02; - send_keyboard_mouse_status(); - mouse_update = 0; - break; - } - break; - - case KeyPress: - key_event = (XKeyEvent *) &report; - charcount = XLookupString(key_event, buffer, bufsize, &keysym, &compose); - xkeypress(keysym, 0); - break; - - case KeyRelease: - key_event = (XKeyEvent *) &report; - charcount = XLookupString(key_event, buffer, bufsize, &keysym, &compose); - xkeypress(keysym, 1); - break; - - case MotionNotify: - pointer_event = (XPointerMovedEvent *) &report; - current_x = pointer_event->x; - current_y = pointer_event->y; - mouse_update = 1; -//BX_INFO(("xxx: motionNotify x,y=(%d,%d)", current_x, current_y)); - break; - - case EnterNotify: - enter_event = (XEnterWindowEvent *) &report; - prev_x = current_x = enter_event->x; - prev_y = current_y = enter_event->y; -//BX_INFO(("xxx: enterNotify x,y=(%d,%d)", current_x, current_y)); - break; - - case LeaveNotify: - leave_event = (XLeaveWindowEvent *) &report; - prev_x = current_x = -1; - prev_y = current_y = -1; -//BX_INFO(("xxx: LeaveNotify x,y set to -1")); - break; - - case MapNotify: - /* screen needs redraw, since X would have tossed previous - * requests before window mapped - */ -//BX_INFO(("xxx: mapnotify: found")); - //retval = 1; - break; - - default: - // (mch) Ignore... - BX_DEBUG(("XXX: default Xevent type")); - /* all events selected by StructureNotifyMask are thrown away here, - * since nothing is done with them */ - break; - } /* end switch */ - } /* end while */ - - if (mouse_update) { - BX_DEBUG(("XXX: bottom, send status")); - send_keyboard_mouse_status(); - } -} - - - void -send_keyboard_mouse_status(void) -{ - BX_DEBUG(("XXX: prev=(%d,%d) curr=(%d,%d)", - prev_x, prev_y, current_x, current_y)); - - if ( (prev_x!=-1) && (current_x!=-1) && (prev_y!=-1) && (current_y!=-1)) { - int dx, dy; - - // (mch) consider warping here - dx = current_x - prev_x - warp_dx; - dy = -(current_y - prev_y - warp_dy); - warp_cursor(warp_home_x-current_x, warp_home_y-current_y); - -//BX_INFO(("xxx: MOUSE_MOTION: dx=%d, dy=%d", (int) dx, (int) dy)); - DEV_mouse_motion (dx, dy, mouse_button_state); - //if (warped) { - // prev_x = current_x = -1; - // prev_y = current_y = -1; - // } - //else { - prev_x = current_x; - prev_y = current_y; - // } - } - else { - if ( (current_x!=-1) && (current_y!=-1)) { - prev_x = current_x; - prev_y = current_y; - } - else { - prev_x = current_x = -1; - prev_y = current_y = -1; - } - } -} - - void -bx_x_gui_c::flush(void) -{ - if (bx_x_display) - XFlush(bx_x_display); -} - - - void -xkeypress(KeySym keysym, int press_release) -{ - Bit32u key_event; - - /* Old (no mapping) behavior */ - if(!bx_options.keyboard.OuseMapping->get()){ - - // this depends on the fact that the X11 keysyms which - // correspond to the ascii characters space .. tilde - // are in consequtive order. - if ((keysym >= XK_space) && (keysym <= XK_asciitilde)) { - key_event = ascii_to_key_event[keysym - XK_space]; - } - else switch (keysym) { - case XK_KP_1: -#ifdef XK_KP_End - case XK_KP_End: -#endif - key_event = BX_KEY_KP_END; break; - - case XK_KP_2: -#ifdef XK_KP_Down - case XK_KP_Down: -#endif - key_event = BX_KEY_KP_DOWN; break; - - case XK_KP_3: -#ifdef XK_KP_Page_Down - case XK_KP_Page_Down: -#endif - key_event = BX_KEY_KP_PAGE_DOWN; break; - - case XK_KP_4: -#ifdef XK_KP_Left - case XK_KP_Left: -#endif - key_event = BX_KEY_KP_LEFT; break; - - case XK_KP_5: -#ifdef XK_KP_Begin - case XK_KP_Begin: -#endif - key_event = BX_KEY_KP_5; break; - - case XK_KP_6: -#ifdef XK_KP_Right - case XK_KP_Right: -#endif - key_event = BX_KEY_KP_RIGHT; break; - - case XK_KP_7: -#ifdef XK_KP_Home - case XK_KP_Home: -#endif - key_event = BX_KEY_KP_HOME; break; - - case XK_KP_8: -#ifdef XK_KP_Up - case XK_KP_Up: -#endif - key_event = BX_KEY_KP_UP; break; - - case XK_KP_9: -#ifdef XK_KP_Page_Up - case XK_KP_Page_Up: -#endif - key_event = BX_KEY_KP_PAGE_UP; break; - - case XK_KP_0: -#ifdef XK_KP_Insert - case XK_KP_Insert: -#endif - key_event = BX_KEY_KP_INSERT; break; - - case XK_KP_Decimal: -#ifdef XK_KP_Delete - case XK_KP_Delete: -#endif - key_event = BX_KEY_KP_DELETE; break; - -#ifdef XK_KP_Enter - case XK_KP_Enter: key_event = BX_KEY_KP_ENTER; break; -#endif - - case XK_KP_Subtract: key_event = BX_KEY_KP_SUBTRACT; break; - case XK_KP_Add: key_event = BX_KEY_KP_ADD; break; - - case XK_KP_Multiply: key_event = BX_KEY_KP_MULTIPLY; break; - case XK_KP_Divide: key_event = BX_KEY_KP_DIVIDE; break; - - - case XK_Up: key_event = BX_KEY_UP; break; - case XK_Down: key_event = BX_KEY_DOWN; break; - case XK_Left: key_event = BX_KEY_LEFT; break; - case XK_Right: key_event = BX_KEY_RIGHT; break; - - - case XK_Delete: key_event = BX_KEY_DELETE; break; - case XK_BackSpace: key_event = BX_KEY_BACKSPACE; break; - case XK_Tab: key_event = BX_KEY_TAB; break; -#ifdef XK_ISO_Left_Tab - case XK_ISO_Left_Tab: key_event = BX_KEY_TAB; break; -#endif - case XK_Return: key_event = BX_KEY_ENTER; break; - case XK_Escape: key_event = BX_KEY_ESC; break; - case XK_F1: key_event = BX_KEY_F1; break; - case XK_F2: key_event = BX_KEY_F2; break; - case XK_F3: key_event = BX_KEY_F3; break; - case XK_F4: key_event = BX_KEY_F4; break; - case XK_F5: key_event = BX_KEY_F5; break; - case XK_F6: key_event = BX_KEY_F6; break; - case XK_F7: key_event = BX_KEY_F7; break; - case XK_F8: key_event = BX_KEY_F8; break; - case XK_F9: key_event = BX_KEY_F9; break; - case XK_F10: key_event = BX_KEY_F10; break; - case XK_F11: key_event = BX_KEY_F11; break; - case XK_F12: key_event = BX_KEY_F12; break; - case XK_Control_L: key_event = BX_KEY_CTRL_L; break; -#ifdef XK_Control_R - case XK_Control_R: key_event = BX_KEY_CTRL_R; break; -#endif - case XK_Shift_L: key_event = BX_KEY_SHIFT_L; break; - case XK_Shift_R: key_event = BX_KEY_SHIFT_R; break; - case XK_Alt_L: key_event = BX_KEY_ALT_L; break; -#ifdef XK_Alt_R - case XK_Alt_R: key_event = BX_KEY_ALT_R; break; -#endif - case XK_Caps_Lock: key_event = BX_KEY_CAPS_LOCK; break; - case XK_Num_Lock: key_event = BX_KEY_NUM_LOCK; break; -#ifdef XK_Scroll_Lock - case XK_Scroll_Lock: key_event = BX_KEY_SCRL_LOCK; break; -#endif -#ifdef XK_Print - case XK_Print: key_event = BX_KEY_PRINT; break; -#endif -#ifdef XK_Pause - case XK_Pause: key_event = BX_KEY_PAUSE; break; -#endif - - case XK_Insert: key_event = BX_KEY_INSERT; break; - case XK_Home: key_event = BX_KEY_HOME; break; - case XK_End: key_event = BX_KEY_END; break; - case XK_Page_Up: key_event = BX_KEY_PAGE_UP; break; - case XK_Page_Down: key_event = BX_KEY_PAGE_DOWN; break; - - default: - BX_ERROR(( "xkeypress(): keysym %x unhandled!", (unsigned) keysym )); - return; - break; - } - } - else { - /* use mapping */ - BXKeyEntry *entry = bx_keymap.findHostKey (keysym); - if (!entry) { - BX_ERROR(( "xkeypress(): keysym %x unhandled!", (unsigned) keysym )); - return; - } - key_event = entry->baseKey; - } - - if (press_release) - key_event |= BX_KEY_RELEASED; - - DEV_kbd_gen_scancode(key_event); -} - - - void -bx_x_gui_c::clear_screen(void) -{ - XClearArea(bx_x_display, win, 0, bx_headerbar_y, dimension_x, dimension_y-bx_headerbar_y, 0); -} - - - - - void -bx_x_gui_c::text_update(Bit8u *old_text, Bit8u *new_text, - unsigned long cursor_x, unsigned long cursor_y, - bx_vga_tminfo_t tm_info, unsigned nrows) -{ - unsigned char *old_line, *new_line; - unsigned char cChar; - unsigned int curs, hchars, i, j, offset, rows, x, y, xc, yc, yc2; - unsigned new_foreground, new_background; - Bit8u cfwidth, cfheight, cfheight2, font_col, font_row, font_row2; - bx_bool force_update=0; - unsigned char cell[64]; - - UNUSED(nrows); - if (charmap_updated) { - BX_INFO(("charmap update. Font Height is %d",font_height)); - for (unsigned c = 0; c<256; c++) { - if (char_changed[c]) { - XFreePixmap(bx_x_display, vgafont[c]); - bx_bool gfxchar = tm_info.line_graphics && ((c & 0xE0) == 0xC0); - j = 0; - memset(cell, 0, sizeof(cell)); - for(i=0; i>1); - cell[i] |= ((vga_charmap[(c<<5)+j] & 0x20)>>3); - cell[i] |= ((vga_charmap[(c<<5)+j] & 0x40)>>5); - cell[i] |= ((vga_charmap[(c<<5)+j] & 0x80)>>7); - if (gfxchar) { - cell[i+1] = (vga_charmap[(c<<5)+j] & 0x01); - } - j++; - } - - vgafont[c]=XCreateBitmapFromData(bx_x_display, win, - (const char*)cell, - font_width, font_height); - if(vgafont[c] == None) - BX_PANIC(("Can't create vga font [%d]", c)); - char_changed[c] = 0; - } - } - force_update = 1; - charmap_updated = 0; - } - - if((tm_info.h_panning != h_panning) || (tm_info.v_panning != v_panning)) { - force_update = 1; - h_panning = tm_info.h_panning; - v_panning = tm_info.v_panning; - } - - // first invalidate character at previous and new cursor location - if ( (prev_cursor_y < text_rows) && (prev_cursor_x < text_cols) ) { - curs = prev_cursor_y * tm_info.line_offset + prev_cursor_x * 2; - old_text[curs] = ~new_text[curs]; - } - if((tm_info.cs_start <= tm_info.cs_end) && (tm_info.cs_start < font_height) && - (cursor_y < text_rows) && (cursor_x < text_cols)) { - curs = cursor_y * tm_info.line_offset + cursor_x * 2; - old_text[curs] = ~new_text[curs]; - } else { - curs = 0xffff; - } - - rows = text_rows; - if (v_panning) rows++; - y = 0; - do { - hchars = text_cols; - if (h_panning) hchars++; - if (v_panning) { - if (y == 0) { - yc = bx_headerbar_y; - font_row = v_panning; - cfheight = font_height - v_panning; - } else { - yc = y * font_height + bx_headerbar_y - v_panning; - font_row = 0; - if (rows == 1) { - cfheight = v_panning; - } else { - cfheight = font_height; - } - } - } else { - yc = y * font_height + bx_headerbar_y; - font_row = 0; - cfheight = font_height; - } - new_line = new_text; - old_line = old_text; - x = 0; - offset = y * tm_info.line_offset; - do { - if (h_panning) { - if (hchars > text_cols) { - xc = 0; - font_col = h_panning; - cfwidth = font_width - h_panning; - } else { - xc = x * font_width - h_panning; - font_col = 0; - if (hchars == 1) { - cfwidth = h_panning; - } else { - cfwidth = font_width; - } - } - } else { - xc = x * font_width; - font_col = 0; - cfwidth = font_width; - } - if ( force_update || (old_text[0] != new_text[0]) - || (old_text[1] != new_text[1]) ) { - - cChar = new_text[0]; - new_foreground = new_text[1] & 0x0f; - new_background = (new_text[1] & 0xf0) >> 4; - - XSetForeground(bx_x_display, gc, col_vals[DEV_vga_get_actl_pal_idx(new_foreground)]); - XSetBackground(bx_x_display, gc, col_vals[DEV_vga_get_actl_pal_idx(new_background)]); - - XCopyPlane(bx_x_display, vgafont[cChar], win, gc, font_col, font_row, cfwidth, cfheight, - xc, yc, 1); - if (offset == curs) { - XSetForeground(bx_x_display, gc, col_vals[DEV_vga_get_actl_pal_idx(new_background)]); - XSetBackground(bx_x_display, gc, col_vals[DEV_vga_get_actl_pal_idx(new_foreground)]); - if (font_row == 0) { - yc2 = yc + tm_info.cs_start; - font_row2 = tm_info.cs_start; - cfheight2 = tm_info.cs_end - tm_info.cs_start + 1; - } else { - if (v_panning > tm_info.cs_start) { - yc2 = yc; - font_row2 = font_row; - cfheight2 = tm_info.cs_end - v_panning + 1; - } else { - yc2 = yc + tm_info.cs_start - v_panning; - font_row2 = tm_info.cs_start; - cfheight2 = tm_info.cs_end - tm_info.cs_start + 1; - } - } - XCopyPlane(bx_x_display, vgafont[cChar], win, gc, font_col, font_row2, cfwidth, - cfheight2, xc, yc2, 1); - } - } - x++; - new_text+=2; - old_text+=2; - offset+=2; - } while (--hchars); - y++; - new_text = new_line + tm_info.line_offset; - old_text = old_line + tm_info.line_offset; - } while (--rows); - - prev_cursor_x = cursor_x; - prev_cursor_y = cursor_y; - - XFlush(bx_x_display); -} - - int -bx_x_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes) -{ - int len; - Bit8u *tmp = (Bit8u *)XFetchBytes (bx_x_display, &len); - // according to man XFetchBytes, tmp must be freed by XFree(). So allocate - // a new buffer with "new". The keyboard code will free it with delete [] - // when the paste is done. - Bit8u *buf = new Bit8u[len]; - memcpy (buf, tmp, len); - *bytes = buf; - *nbytes = len; - XFree (tmp); - return 1; -} - - int -bx_x_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len) -{ - // this writes data to the clipboard. - BX_INFO (("storing %d bytes to X windows clipboard", len)); - XSetSelectionOwner(bx_x_display, XA_PRIMARY, None, CurrentTime); - XStoreBytes (bx_x_display, (char *)text_snapshot, len); - return 1; -} - - - void -bx_x_gui_c::graphics_tile_update(Bit8u *tile, unsigned x0, unsigned y0) -{ - unsigned x, y; - unsigned color, offset; - Bit8u b0, b1, b2, b3; - - Bit16u *tile16 = (Bit16u *)tile; - switch (vga_bpp) { - case 32: // 32 bits per pixel - if (ximage->byte_order == LSBFirst) { - memcpy(&ximage->data[0], tile, x_tilesize*y_tilesize*4); - } - else { // MSBFirst - for (y=0; ydata[offset + 0] = tile[(y*x_tilesize + x)*4 + 3]; - ximage->data[offset + 1] = tile[(y*x_tilesize + x)*4 + 2]; - ximage->data[offset + 2] = tile[(y*x_tilesize + x)*4 + 1]; - ximage->data[offset + 3] = tile[(y*x_tilesize + x)*4]; - } - } - } - break; - case 24: // 24 bits per pixel - for (y=0; ybyte_order == LSBFirst) { - ximage->data[offset + 0] = tile[(y*x_tilesize + x)*3]; - ximage->data[offset + 1] = tile[(y*x_tilesize + x)*3 + 1]; - ximage->data[offset + 2] = tile[(y*x_tilesize + x)*3 + 2]; - } - else { // MSBFirst - ximage->data[offset + 0] = tile[(y*x_tilesize + x)*3 + 2]; - ximage->data[offset + 1] = tile[(y*x_tilesize + x)*3 + 1]; - ximage->data[offset + 2] = tile[(y*x_tilesize + x)*3]; - } - break; - case 32: // 32 bits per pixel - offset = imWide*y + 4*x; - if (ximage->byte_order == LSBFirst) { - ximage->data[offset + 0] = tile[(y*x_tilesize + x)*3]; - ximage->data[offset + 1] = tile[(y*x_tilesize + x)*3 + 1]; - ximage->data[offset + 2] = tile[(y*x_tilesize + x)*3 + 2]; - ximage->data[offset + 3] = 0; - } - else { // MSBFirst - ximage->data[offset + 0] = 0; - ximage->data[offset + 1] = tile[(y*x_tilesize + x)*3 + 2]; - ximage->data[offset + 2] = tile[(y*x_tilesize + x)*3 + 1]; - ximage->data[offset + 3] = tile[(y*x_tilesize + x)*3]; - } - break; - } - } - } - break; - case 16: // 16 bits per pixel - for (y=0; ybyte_order == LSBFirst) { - ximage->data[offset + 0] = tile[(y*x_tilesize + x)*2]; - ximage->data[offset + 1] = tile[(y*x_tilesize + x)*2 + 1]; - } - else { // MSBFirst - ximage->data[offset + 0] = tile[(y*x_tilesize + x)*2 + 1]; - ximage->data[offset + 1] = tile[(y*x_tilesize + x)*2]; - } - break; - case 24: // 24 bits per pixel - offset = imWide*y + 3*x; - b0 = (tile16[y*x_tilesize + x] & 0x001f) << 3; - b1 = (tile16[y*x_tilesize + x] & 0x07e0) >> 3; - b2 = (tile16[y*x_tilesize + x] & 0xF800) >> 8; - if (ximage->byte_order == LSBFirst) { - ximage->data[offset + 0] = b0; - ximage->data[offset + 1] = b1; - ximage->data[offset + 2] = b2; - } - else { // MSBFirst - ximage->data[offset + 0] = b2; - ximage->data[offset + 1] = b1; - ximage->data[offset + 2] = b0; - } - break; - case 32: // 32 bits per pixel - offset = imWide*y + 4*x; - b0 = (tile16[y*x_tilesize + x] & 0x001f) << 3; - b1 = (tile16[y*x_tilesize + x] & 0x07e0) >> 3; - b2 = (tile16[y*x_tilesize + x] & 0xF800) >> 8; - if (ximage->byte_order == LSBFirst) { - ximage->data[offset + 0] = b0; - ximage->data[offset + 1] = b1; - ximage->data[offset + 2] = b2; - ximage->data[offset + 3] = 0; - } - else { // MSBFirst - ximage->data[offset + 0] = 0; - ximage->data[offset + 1] = b2; - ximage->data[offset + 2] = b1; - ximage->data[offset + 3] = b0; - } - break; - } - } - } - break; - case 15: // 15 bits per pixel - for (y=0; y> 7; - if (ximage->byte_order == LSBFirst) { - ximage->data[offset + 0] = b0; - ximage->data[offset + 1] = b1; - } - else { // MSBFirst - ximage->data[offset + 0] = b1; - ximage->data[offset + 1] = b0; - } - break; - case 24: // 24 bits per pixel - offset = imWide*y + 3*x; - b0 = (tile16[y*x_tilesize + x] & 0x001f) << 3; - b1 = (tile16[y*x_tilesize + x] & 0x03e0) >> 2; - b2 = (tile16[y*x_tilesize + x] & 0x7c00) >> 7; - if (ximage->byte_order == LSBFirst) { - ximage->data[offset + 0] = b0; - ximage->data[offset + 1] = b1; - ximage->data[offset + 2] = b2; - } - else { // MSBFirst - ximage->data[offset + 0] = b2; - ximage->data[offset + 1] = b1; - ximage->data[offset + 2] = b0; - } - break; - case 32: // 32 bits per pixel - offset = imWide*y + 4*x; - b0 = (tile16[y*x_tilesize + x] & 0x001f) << 3; - b1 = (tile16[y*x_tilesize + x] & 0x03e0) >> 2; - b2 = (tile16[y*x_tilesize + x] & 0x7c00) >> 7; - if (ximage->byte_order == LSBFirst) { - ximage->data[offset + 0] = b0; - ximage->data[offset + 1] = b1; - ximage->data[offset + 2] = b2; - ximage->data[offset + 3] = 0; - } - else { // MSBFirst - ximage->data[offset + 0] = 0; - ximage->data[offset + 1] = b2; - ximage->data[offset + 2] = b1; - ximage->data[offset + 3] = b0; - } - break; - } - } - } - break; - default: // 8 bits per pixel - for (y=0; ydata[imWide*y + x] = color; - break; - case 16: // 16 bits per pixel - offset = imWide*y + 2*x; - b0 = color >> 0; - b1 = color >> 8; - if (ximage->byte_order == LSBFirst) { - ximage->data[offset + 0] = b0; - ximage->data[offset + 1] = b1; - } - else { // MSBFirst - ximage->data[offset + 0] = b1; - ximage->data[offset + 1] = b0; - } - break; - case 24: // 24 bits per pixel - offset = imWide*y + 3*x; - b0 = color >> 0; - b1 = color >> 8; - b2 = color >> 16; - if (ximage->byte_order == LSBFirst) { - ximage->data[offset + 0] = b0; - ximage->data[offset + 1] = b1; - ximage->data[offset + 2] = b2; - } - else { // MSBFirst - ximage->data[offset + 0] = b2; - ximage->data[offset + 1] = b1; - ximage->data[offset + 2] = b0; - } - break; - case 32: // 32 bits per pixel - offset = imWide*y + 4*x; - b0 = color >> 0; - b1 = color >> 8; - b2 = color >> 16; - b3 = color >> 24; - if (ximage->byte_order == LSBFirst) { - ximage->data[offset + 0] = b0; - ximage->data[offset + 1] = b1; - ximage->data[offset + 2] = b2; - ximage->data[offset + 3] = b3; - } - else { // MSBFirst - ximage->data[offset + 0] = b3; - ximage->data[offset + 1] = b2; - ximage->data[offset + 2] = b1; - ximage->data[offset + 3] = b0; - } - break; - default: - BX_PANIC(("X_graphics_tile_update: bits_per_pixel %u not implemented", - (unsigned) imBPP)); - break; - } - } - } - } - XPutImage(bx_x_display, win, gc, ximage, 0, 0, x0, y0+bx_headerbar_y, - x_tilesize, y_tilesize); -} - - - bx_bool -bx_x_gui_c::palette_change(unsigned index, unsigned red, unsigned green, unsigned blue) -{ - // returns: 0=no screen update needed (color map change has direct effect) - // 1=screen updated needed (redraw using current colormap) - XColor color; - - color.flags = DoRed | DoGreen | DoBlue; - color.red = red << 8; - color.green = green << 8; - color.blue = blue << 8; - - if (bx_options.Oprivate_colormap->get ()) { - color.pixel = index; - XStoreColor(bx_x_display, default_cmap, &color); - return(0); // no screen update needed - } - else { - XAllocColor(bx_x_display, DefaultColormap(bx_x_display, bx_x_screen_num), - &color); - col_vals[index] = color.pixel; - return(1); // screen update needed - } -} - - - void -bx_x_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, unsigned fwidth, unsigned bpp) -{ - if ((bpp <= imBPP) && ((bpp == 8) || (bpp == 15) || (bpp == 16) || (bpp == 24) || (bpp == 32))) { - vga_bpp = bpp; - } else { - BX_PANIC(("%d bpp graphics mode not supported", bpp)); - } - if (fheight > 0) { - font_height = fheight; - font_width = fwidth; - text_cols = x / font_width; - text_rows = y / font_height; - } - if ( (x != dimension_x) || (y != (dimension_y-bx_headerbar_y)) ) { - XSizeHints hints; - long supplied_return; - - if ( XGetWMNormalHints(bx_x_display, win, &hints, &supplied_return) && - supplied_return & PMaxSize ) { - hints.max_width = hints.min_width = x; - hints.max_height = hints.min_height = y+bx_headerbar_y; - XSetWMNormalHints(bx_x_display, win, &hints); - } - XResizeWindow(bx_x_display, win, x, y+bx_headerbar_y); - dimension_x = x; - dimension_y = y + bx_headerbar_y; - } -} - - - void -bx_x_gui_c::show_headerbar(void) -{ - unsigned xorigin; - int xleft, xright; - - // clear header bar area to white - XFillRectangle(bx_x_display, win, gc_headerbar_inv, 0,0, dimension_x, bx_headerbar_y); - - xleft = 0; - xright = dimension_x; - for (unsigned i=0; i= BX_MAX_PIXMAPS) { - BX_PANIC(("x: too many pixmaps, increase BX_MAX_PIXMAPS")); - } - - bx_bitmaps[bx_bitmap_entries].bmap = - XCreateBitmapFromData(bx_x_display, win, (const char *) bmap, xdim, ydim); - bx_bitmaps[bx_bitmap_entries].xdim = xdim; - bx_bitmaps[bx_bitmap_entries].ydim = ydim; - if (!bx_bitmaps[bx_bitmap_entries].bmap) { - BX_PANIC(("x: could not create bitmap")); - } - bx_bitmap_entries++; - return(bx_bitmap_entries-1); // return index as handle -} - - - unsigned -bx_x_gui_c::headerbar_bitmap(unsigned bmap_id, unsigned alignment, void (*f)(void)) -{ - unsigned hb_index; - - if ( (bx_headerbar_entries+1) > BX_MAX_HEADERBAR_ENTRIES ) - BX_PANIC(("x: too many headerbar entries, increase BX_MAX_HEADERBAR_ENTRIES")); - - bx_headerbar_entries++; - hb_index = bx_headerbar_entries - 1; - - bx_headerbar_entry[hb_index].bitmap = bx_bitmaps[bmap_id].bmap; - bx_headerbar_entry[hb_index].xdim = bx_bitmaps[bmap_id].xdim; - bx_headerbar_entry[hb_index].ydim = bx_bitmaps[bmap_id].ydim; - bx_headerbar_entry[hb_index].alignment = alignment; - bx_headerbar_entry[hb_index].f = f; - if (alignment == BX_GRAVITY_LEFT) { - bx_headerbar_entry[hb_index].xorigin = bx_bitmap_left_xorigin; - bx_headerbar_entry[hb_index].yorigin = 0; - bx_bitmap_left_xorigin += bx_bitmaps[bmap_id].xdim; - } - else { // BX_GRAVITY_RIGHT - bx_bitmap_right_xorigin += bx_bitmaps[bmap_id].xdim; - bx_headerbar_entry[hb_index].xorigin = bx_bitmap_right_xorigin; - bx_headerbar_entry[hb_index].yorigin = 0; - } - return(hb_index); -} - - void -bx_x_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id) -{ - unsigned xorigin; - - bx_headerbar_entry[hbar_id].bitmap = bx_bitmaps[bmap_id].bmap; - - if (bx_headerbar_entry[hbar_id].alignment == BX_GRAVITY_LEFT) - xorigin = bx_headerbar_entry[hbar_id].xorigin; - else - xorigin = dimension_x - bx_headerbar_entry[hbar_id].xorigin; - XCopyPlane(bx_x_display, bx_headerbar_entry[hbar_id].bitmap, win, gc_headerbar, - 0,0, bx_headerbar_entry[hbar_id].xdim, bx_headerbar_entry[hbar_id].ydim, - xorigin, 0, 1); -} - - - void -headerbar_click(int x, int y) -{ - int xorigin; - - // assuming y is in bounds - UNUSED(y); - for (unsigned i=0; i=xorigin) && (x<(xorigin+int(bx_headerbar_entry[i].xdim))) ) { - bx_headerbar_entry[i].f(); - return; - } - } -} - - void -bx_x_gui_c::exit(void) -{ - if (!x_init_done) return; - - // Delete the font bitmaps - for (int i=0; i<256; i++) { - //if (vgafont[i] != NULL) - XFreePixmap(bx_x_display,vgafont[i]); - } - - if (bx_x_display) - XCloseDisplay (bx_x_display); - BX_INFO(("Exit.")); -} - -static void warp_cursor (int dx, int dy) -{ - if (bx_options.Omouse_enabled->get () && - (warp_dx || warp_dy || dx || dy) - ) { - warp_dx = dx; - warp_dy = dy; - XWarpPointer(bx_x_display, None, None, 0, 0, 0, 0, dx, dy); - } -} - -static void disable_cursor () -{ - static Cursor cursor; - static unsigned cursor_created = 0; - - static int shape_width = 16, - shape_height = 16, - mask_width = 16, - mask_height = 16; - - static uint32 shape_bits[(16*16)/32] = { - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - }; - static uint32 mask_bits[(16*16)/32] = { - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - }; - - if (!cursor_created) { - Pixmap shape, mask; - XColor white, black; - shape = XCreatePixmapFromBitmapData(bx_x_display, - RootWindow(bx_x_display,bx_x_screen_num), - (char*)shape_bits, - shape_width, - shape_height, - 1, 0, 1); - mask = XCreatePixmapFromBitmapData(bx_x_display, - RootWindow(bx_x_display,bx_x_screen_num), - (char*)mask_bits, - mask_width, - mask_height, - 1, 0, 1); - XParseColor(bx_x_display, default_cmap, "black", &black); - XParseColor(bx_x_display, default_cmap, "white", &white); - cursor = XCreatePixmapCursor(bx_x_display, shape, mask, - &white, &black, 1, 1); - cursor_created = 1; - } - - XDefineCursor(bx_x_display, win, cursor); -} - -static void enable_cursor () -{ - XUndefineCursor(bx_x_display, win); -} - -/* convertStringToXKeysym is a keymap callback - * used when reading the keymap file. - * It converts a Symblic String to a GUI Constant - * - * It returns a Bit32u constant or BX_KEYMAP_UNKNOWN if it fails - */ -static Bit32u convertStringToXKeysym (const char *string) -{ - if (strncmp ("XK_", string, 3) != 0) - return BX_KEYMAP_UNKNOWN; - KeySym keysym=XStringToKeysym(string+3); - - // failure, return unknown - if(keysym==NoSymbol) return BX_KEYMAP_UNKNOWN; - - return((Bit32u)keysym); -} - -#if BX_USE_IDLE_HACK - -/* BX_USE_IDLE_HACK: a small idle hack by - * Roland.Mainz@informatik.med.uni-giessen.de to prevent bochs - * from consuming 100% CPU time even when it is not required (for - * example, the OS in the emulator calls HLT to wait for an interupt) - * pro: - * - no more 100% CPU usage - * contra: - * - we're sleeping too long - * - bochs still consumes ~10%-20% CPU time while executing an idle - * linux kernel - * - this is an hack - */ - -/* XPeekEvent() with timeout - * (adopted from mozilla/gfx/src/xprint/xprintutil_printtofile.c#XNextEventTimeout()) - */ -static -Bool XPeekEventTimeout( Display *display, XEvent *event_return, struct timeval *timeout ) -{ - int res; - fd_set readfds; - int display_fd = XConnectionNumber(display); - - /* small shortcut... */ - if( timeout == NULL ) - { - XPeekEvent(display, event_return); - return(True); - } - - FD_ZERO(&readfds); - FD_SET(display_fd, &readfds); - - /* Note/bug: In the case of internal X events (like used to trigger callbacks - * registered by XpGetDocumentData()&co.) select() will return with "new info" - * - but XNextEvent() below processes these _internal_ events silently - and - * will block if there are no other non-internal events. - * The workaround here is to check with XEventsQueued() if there are non-internal - * events queued - if not select() will be called again - unfortunately we use - * the old timeout here instead of the "remaining" time... (this only would hurt - * if the timeout would be really long - but for current use with values below - * 1/2 secs it does not hurt... =:-) - */ - while( XEventsQueued(display, QueuedAfterFlush) == 0 ) - { - res = select(display_fd+1, &readfds, NULL, NULL, timeout); - - switch(res) - { - case -1: /* select() error - should not happen */ - perror("XPeekEventTimeout: select() failure"); - return(False); - case 0: /* timeout */ - return(False); - } - } - - XPeekEvent(display, event_return); - return(True); -} - -#if BX_USE_IDLE_HACK -void bx_x_gui_c::sim_is_idle () { - XEvent dummy; - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 1000; /* 1/1000 s */ - XPeekEventTimeout(bx_x_display, &dummy, &timeout); -} -#endif -#endif /* BX_USE_IDLE_HACK */ - -#endif /* if BX_WITH_X11 */ diff --git a/tools/ioemu/hw/adb.c b/tools/ioemu/hw/adb.c new file mode 100644 index 0000000000..36c4aecd25 --- /dev/null +++ b/tools/ioemu/hw/adb.c @@ -0,0 +1,386 @@ +/* + * QEMU ADB support + * + * Copyright (c) 2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +/* ADB commands */ +#define ADB_BUSRESET 0x00 +#define ADB_FLUSH 0x01 +#define ADB_WRITEREG 0x08 +#define ADB_READREG 0x0c + +/* ADB device commands */ +#define ADB_CMD_SELF_TEST 0xff +#define ADB_CMD_CHANGE_ID 0xfe +#define ADB_CMD_CHANGE_ID_AND_ACT 0xfd +#define ADB_CMD_CHANGE_ID_AND_ENABLE 0x00 + +/* ADB default device IDs (upper 4 bits of ADB command byte) */ +#define ADB_DONGLE 1 +#define ADB_KEYBOARD 2 +#define ADB_MOUSE 3 +#define ADB_TABLET 4 +#define ADB_MODEM 5 +#define ADB_MISC 7 + +/* error codes */ +#define ADB_RET_NOTPRESENT (-2) + +int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len) +{ + ADBDevice *d; + int devaddr, cmd, i; + + cmd = buf[0] & 0xf; + if (cmd == ADB_BUSRESET) { + for(i = 0; i < s->nb_devices; i++) { + d = &s->devices[i]; + if (d->devreset) { + d->devreset(d); + } + } + return 0; + } + devaddr = buf[0] >> 4; + for(i = 0; i < s->nb_devices; i++) { + d = &s->devices[i]; + if (d->devaddr == devaddr) { + return d->devreq(d, obuf, buf, len); + } + } + return ADB_RET_NOTPRESENT; +} + +/* XXX: move that to cuda ? */ +int adb_poll(ADBBusState *s, uint8_t *obuf) +{ + ADBDevice *d; + int olen, i; + uint8_t buf[1]; + + olen = 0; + for(i = 0; i < s->nb_devices; i++) { + if (s->poll_index >= s->nb_devices) + s->poll_index = 0; + d = &s->devices[s->poll_index]; + buf[0] = ADB_READREG | (d->devaddr << 4); + olen = adb_request(s, obuf + 1, buf, 1); + /* if there is data, we poll again the same device */ + if (olen > 0) { + obuf[0] = buf[0]; + olen++; + break; + } + s->poll_index++; + } + return olen; +} + +ADBDevice *adb_register_device(ADBBusState *s, int devaddr, + ADBDeviceRequest *devreq, + ADBDeviceReset *devreset, + void *opaque) +{ + ADBDevice *d; + if (s->nb_devices >= MAX_ADB_DEVICES) + return NULL; + d = &s->devices[s->nb_devices++]; + d->bus = s; + d->devaddr = devaddr; + d->devreq = devreq; + d->devreset = devreset; + d->opaque = opaque; + return d; +} + +/***************************************************************/ +/* Keyboard ADB device */ + +typedef struct KBDState { + uint8_t data[128]; + int rptr, wptr, count; +} KBDState; + +static const uint8_t pc_to_adb_keycode[256] = { + 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48, + 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1, + 2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9, + 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96, + 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83, + 84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 94, 0, 93, 0, 0, 0, 0, 0, 0,104,102, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,125, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 75, 0, 0,124, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0,115, 62,116, 0, 59, 0, 60, 0,119, + 61,121,114,117, 0, 0, 0, 0, 0, 0, 0, 55,126, 0,127, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static void adb_kbd_put_keycode(void *opaque, int keycode) +{ + ADBDevice *d = opaque; + KBDState *s = d->opaque; + + if (s->count < sizeof(s->data)) { + s->data[s->wptr] = keycode; + if (++s->wptr == sizeof(s->data)) + s->wptr = 0; + s->count++; + } +} + +static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf) +{ + static int ext_keycode; + KBDState *s = d->opaque; + int adb_keycode, keycode; + int olen; + + olen = 0; + for(;;) { + if (s->count == 0) + break; + keycode = s->data[s->rptr]; + if (++s->rptr == sizeof(s->data)) + s->rptr = 0; + s->count--; + + if (keycode == 0xe0) { + ext_keycode = 1; + } else { + if (ext_keycode) + adb_keycode = pc_to_adb_keycode[keycode | 0x80]; + else + adb_keycode = pc_to_adb_keycode[keycode & 0x7f]; + obuf[0] = adb_keycode | (keycode & 0x80); + /* NOTE: could put a second keycode if needed */ + obuf[1] = 0xff; + olen = 2; + ext_keycode = 0; + break; + } + } + return olen; +} + +static int adb_kbd_request(ADBDevice *d, uint8_t *obuf, + const uint8_t *buf, int len) +{ + KBDState *s = d->opaque; + int cmd, reg, olen; + + if ((buf[0] & 0x0f) == ADB_FLUSH) { + /* flush keyboard fifo */ + s->wptr = s->rptr = s->count = 0; + return 0; + } + + cmd = buf[0] & 0xc; + reg = buf[0] & 0x3; + olen = 0; + switch(cmd) { + case ADB_WRITEREG: + switch(reg) { + case 2: + /* LED status */ + break; + case 3: + switch(buf[2]) { + case ADB_CMD_SELF_TEST: + break; + case ADB_CMD_CHANGE_ID: + case ADB_CMD_CHANGE_ID_AND_ACT: + case ADB_CMD_CHANGE_ID_AND_ENABLE: + d->devaddr = buf[1] & 0xf; + break; + default: + /* XXX: check this */ + d->devaddr = buf[1] & 0xf; + d->handler = buf[2]; + break; + } + } + break; + case ADB_READREG: + switch(reg) { + case 0: + olen = adb_kbd_poll(d, obuf); + break; + case 1: + break; + case 2: + obuf[0] = 0x00; /* XXX: check this */ + obuf[1] = 0x07; /* led status */ + olen = 2; + break; + case 3: + obuf[0] = d->handler; + obuf[1] = d->devaddr; + olen = 2; + break; + } + break; + } + return olen; +} + +void adb_kbd_init(ADBBusState *bus) +{ + ADBDevice *d; + KBDState *s; + s = qemu_mallocz(sizeof(KBDState)); + d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request, NULL, s); + d->handler = 1; + qemu_add_kbd_event_handler(adb_kbd_put_keycode, d); +} + +/***************************************************************/ +/* Mouse ADB device */ + +typedef struct MouseState { + int buttons_state, last_buttons_state; + int dx, dy, dz; +} MouseState; + +static void adb_mouse_event(void *opaque, + int dx1, int dy1, int dz1, int buttons_state) +{ + ADBDevice *d = opaque; + MouseState *s = d->opaque; + + s->dx += dx1; + s->dy += dy1; + s->dz += dz1; + s->buttons_state = buttons_state; +} + + +static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf) +{ + MouseState *s = d->opaque; + int dx, dy; + + if (s->last_buttons_state == s->buttons_state && + s->dx == 0 && s->dy == 0) + return 0; + + dx = s->dx; + if (dx < -63) + dx = -63; + else if (dx > 63) + dx = 63; + + dy = s->dy; + if (dy < -63) + dy = -63; + else if (dy > 63) + dy = 63; + + s->dx -= dx; + s->dy -= dy; + s->last_buttons_state = s->buttons_state; + + dx &= 0x7f; + dy &= 0x7f; + + if (!(s->buttons_state & MOUSE_EVENT_LBUTTON)) + dy |= 0x80; + if (!(s->buttons_state & MOUSE_EVENT_RBUTTON)) + dx |= 0x80; + + obuf[0] = dy; + obuf[1] = dx; + return 2; +} + +static int adb_mouse_request(ADBDevice *d, uint8_t *obuf, + const uint8_t *buf, int len) +{ + MouseState *s = d->opaque; + int cmd, reg, olen; + + if ((buf[0] & 0x0f) == ADB_FLUSH) { + /* flush mouse fifo */ + s->buttons_state = s->last_buttons_state; + s->dx = 0; + s->dy = 0; + s->dz = 0; + return 0; + } + + cmd = buf[0] & 0xc; + reg = buf[0] & 0x3; + olen = 0; + switch(cmd) { + case ADB_WRITEREG: + switch(reg) { + case 2: + break; + case 3: + switch(buf[2]) { + case ADB_CMD_SELF_TEST: + break; + case ADB_CMD_CHANGE_ID: + case ADB_CMD_CHANGE_ID_AND_ACT: + case ADB_CMD_CHANGE_ID_AND_ENABLE: + d->devaddr = buf[1] & 0xf; + break; + default: + /* XXX: check this */ + d->devaddr = buf[1] & 0xf; + break; + } + } + break; + case ADB_READREG: + switch(reg) { + case 0: + olen = adb_mouse_poll(d, obuf); + break; + case 1: + break; + case 3: + obuf[0] = d->handler; + obuf[1] = d->devaddr; + olen = 2; + break; + } + break; + } + return olen; +} + +void adb_mouse_init(ADBBusState *bus) +{ + ADBDevice *d; + MouseState *s; + + s = qemu_mallocz(sizeof(MouseState)); + d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request, NULL, s); + d->handler = 2; + qemu_add_mouse_event_handler(adb_mouse_event, d); +} diff --git a/tools/ioemu/hw/adlib.c b/tools/ioemu/hw/adlib.c new file mode 100644 index 0000000000..939a7ed036 --- /dev/null +++ b/tools/ioemu/hw/adlib.c @@ -0,0 +1,313 @@ +/* + * QEMU Adlib emulation + * + * Copyright (c) 2004 Vassili Karpov (malc) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +#define dolog(...) AUD_log ("adlib", __VA_ARGS__) +#ifdef DEBUG +#define ldebug(...) dolog (__VA_ARGS__) +#else +#define ldebug(...) +#endif + +#ifdef USE_YMF262 +#define HAS_YMF262 1 +#include "ymf262.h" +void YMF262UpdateOneQEMU(int which, INT16 *dst, int length); +#define SHIFT 2 +#else +#include "fmopl.h" +#define SHIFT 1 +#endif + +#ifdef _WIN32 +#include +#define small_delay() Sleep (1) +#else +#define small_delay() usleep (1) +#endif + +#define IO_READ_PROTO(name) \ + uint32_t name (void *opaque, uint32_t nport) +#define IO_WRITE_PROTO(name) \ + void name (void *opaque, uint32_t nport, uint32_t val) + +static struct { + int port; + int freq; +} conf = {0x220, 44100}; + +typedef struct { + int enabled; + int active; + int cparam; + int64_t ticks; + int bufpos; + int16_t *mixbuf; + double interval; + QEMUTimer *ts, *opl_ts; + SWVoice *voice; + int left, pos, samples, bytes_per_second, old_free; + int refcount; +#ifndef USE_YMF262 + FM_OPL *opl; +#endif +} AdlibState; + +static AdlibState adlib; + +static IO_WRITE_PROTO(adlib_write) +{ + AdlibState *s = opaque; + int a = nport & 3; + int status; + + s->ticks = qemu_get_clock (vm_clock); + s->active = 1; + AUD_enable (s->voice, 1); + +#ifdef USE_YMF262 + status = YMF262Write (0, a, val); +#else + status = OPLWrite (s->opl, a, val); +#endif +} + +static IO_READ_PROTO(adlib_read) +{ + AdlibState *s = opaque; + uint8_t data; + int a = nport & 3; + +#ifdef USE_YMF262 + (void) s; + data = YMF262Read (0, a); +#else + data = OPLRead (s->opl, a); +#endif + return data; +} + +static void OPL_timer (void *opaque) +{ + AdlibState *s = opaque; +#ifdef USE_YMF262 + YMF262TimerOver (s->cparam >> 1, s->cparam & 1); +#else + OPLTimerOver (s->opl, s->cparam); +#endif + qemu_mod_timer (s->opl_ts, qemu_get_clock (vm_clock) + s->interval); +} + +static void YMF262TimerHandler (int c, double interval_Sec) +{ + AdlibState *s = &adlib; + if (interval_Sec == 0.0) { + qemu_del_timer (s->opl_ts); + return; + } + s->cparam = c; + s->interval = ticks_per_sec * interval_Sec; + qemu_mod_timer (s->opl_ts, qemu_get_clock (vm_clock) + s->interval); + small_delay (); +} + +static int write_audio (AdlibState *s, int samples) +{ + int net = 0; + int ss = samples; + while (samples) { + int nbytes = samples << SHIFT; + int wbytes = AUD_write (s->voice, + s->mixbuf + (s->pos << (SHIFT - 1)), + nbytes); + int wsampl = wbytes >> SHIFT; + samples -= wsampl; + s->pos = (s->pos + wsampl) % s->samples; + net += wsampl; + if (!wbytes) + break; + } + if (net > ss) { + dolog ("WARNING: net > ss\n"); + } + return net; +} + +static void timer (void *opaque) +{ + AdlibState *s = opaque; + int elapsed, samples, net = 0; + + if (s->refcount) + dolog ("refcount=%d\n", s->refcount); + + s->refcount += 1; + if (!(s->active && s->enabled)) + goto reset; + + AUD_run (); + + while (s->left) { + int written = write_audio (s, s->left); + net += written; + if (!written) + goto reset2; + s->left -= written; + } + s->pos = 0; + + elapsed = AUD_calc_elapsed (s->voice); + if (!elapsed) + goto reset2; + + /* elapsed = AUD_get_free (s->voice); */ + samples = elapsed >> SHIFT; + if (!samples) + goto reset2; + + samples = audio_MIN (samples, s->samples - s->pos); + if (s->left) + dolog ("left=%d samples=%d elapsed=%d free=%d\n", + s->left, samples, elapsed, AUD_get_free (s->voice)); + + if (!samples) + goto reset2; + +#ifdef USE_YMF262 + YMF262UpdateOneQEMU (0, s->mixbuf + s->pos * 2, samples); +#else + YM3812UpdateOne (s->opl, s->mixbuf + s->pos, samples); +#endif + + while (samples) { + int written = write_audio (s, samples); + net += written; + if (!written) + break; + samples -= written; + } + if (!samples) + s->pos = 0; + s->left = samples; + +reset2: + AUD_adjust (s->voice, net << SHIFT); +reset: + qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + ticks_per_sec / 1024); + s->refcount -= 1; +} + +static void Adlib_fini (AdlibState *s) +{ +#ifdef USE_YMF262 + YMF262Shutdown (); +#else + if (s->opl) { + OPLDestroy (s->opl); + s->opl = NULL; + } +#endif + + if (s->opl_ts) + qemu_free_timer (s->opl_ts); + + if (s->ts) + qemu_free_timer (s->ts); + +#define maybe_free(p) if (p) qemu_free (p) + maybe_free (s->mixbuf); +#undef maybe_free + + s->active = 0; + s->enabled = 0; +} + +void Adlib_init (void) +{ + AdlibState *s = &adlib; + + memset (s, 0, sizeof (*s)); + +#ifdef USE_YMF262 + if (YMF262Init (1, 14318180, conf.freq)) { + dolog ("YMF262Init %d failed\n", conf.freq); + return; + } + else { + YMF262SetTimerHandler (0, YMF262TimerHandler, 0); + s->enabled = 1; + } +#else + s->opl = OPLCreate (OPL_TYPE_YM3812, 3579545, conf.freq); + if (!s->opl) { + dolog ("OPLCreate %d failed\n", conf.freq); + return; + } + else { + OPLSetTimerHandler (s->opl, YMF262TimerHandler, 0); + s->enabled = 1; + } +#endif + + s->opl_ts = qemu_new_timer (vm_clock, OPL_timer, s); + if (!s->opl_ts) { + dolog ("Can not get timer for adlib emulation\n"); + Adlib_fini (s); + return; + } + + s->ts = qemu_new_timer (vm_clock, timer, s); + if (!s->opl_ts) { + dolog ("Can not get timer for adlib emulation\n"); + Adlib_fini (s); + return; + } + + s->voice = AUD_open (s->voice, "adlib", conf.freq, SHIFT, AUD_FMT_S16); + if (!s->voice) { + Adlib_fini (s); + return; + } + + s->bytes_per_second = conf.freq << SHIFT; + s->samples = AUD_get_buffer_size (s->voice) >> SHIFT; + s->mixbuf = qemu_mallocz (s->samples << SHIFT); + + if (!s->mixbuf) { + dolog ("not enough memory for adlib mixing buffer (%d)\n", + s->samples << SHIFT); + Adlib_fini (s); + return; + } + register_ioport_read (0x388, 4, 1, adlib_read, s); + register_ioport_write (0x388, 4, 1, adlib_write, s); + + register_ioport_read (conf.port, 4, 1, adlib_read, s); + register_ioport_write (conf.port, 4, 1, adlib_write, s); + + register_ioport_read (conf.port + 8, 2, 1, adlib_read, s); + register_ioport_write (conf.port + 8, 2, 1, adlib_write, s); + + qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1); +} diff --git a/tools/ioemu/hw/cirrus_vga.c b/tools/ioemu/hw/cirrus_vga.c new file mode 100644 index 0000000000..7c34c57899 --- /dev/null +++ b/tools/ioemu/hw/cirrus_vga.c @@ -0,0 +1,3115 @@ +/* + * QEMU Cirrus CLGD 54xx VGA Emulator. + * + * Copyright (c) 2004 Fabrice Bellard + * Copyright (c) 2004 Makoto Suzuki (suzu) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* + * Reference: Finn Thogersons' VGADOC4b + * available at http://home.worldonline.dk/~finth/ + */ +#include "vl.h" +#include "vga_int.h" + +/* + * TODO: + * - add support for WRITEMASK (GR2F) + * - optimize linear mappings + * - optimize bitblt functions + */ + +//#define DEBUG_CIRRUS +//#define DEBUG_BITBLT + +/*************************************** + * + * definitions + * + ***************************************/ + +#define qemu_MIN(a,b) ((a) < (b) ? (a) : (b)) + +// ID +#define CIRRUS_ID_CLGD5422 (0x23<<2) +#define CIRRUS_ID_CLGD5426 (0x24<<2) +#define CIRRUS_ID_CLGD5424 (0x25<<2) +#define CIRRUS_ID_CLGD5428 (0x26<<2) +#define CIRRUS_ID_CLGD5430 (0x28<<2) +#define CIRRUS_ID_CLGD5434 (0x2A<<2) +#define CIRRUS_ID_CLGD5436 (0x2B<<2) +#define CIRRUS_ID_CLGD5446 (0x2E<<2) + +// sequencer 0x07 +#define CIRRUS_SR7_BPP_VGA 0x00 +#define CIRRUS_SR7_BPP_SVGA 0x01 +#define CIRRUS_SR7_BPP_MASK 0x0e +#define CIRRUS_SR7_BPP_8 0x00 +#define CIRRUS_SR7_BPP_16_DOUBLEVCLK 0x02 +#define CIRRUS_SR7_BPP_24 0x04 +#define CIRRUS_SR7_BPP_16 0x06 +#define CIRRUS_SR7_BPP_32 0x08 +#define CIRRUS_SR7_ISAADDR_MASK 0xe0 + +// sequencer 0x0f +#define CIRRUS_MEMSIZE_512k 0x08 +#define CIRRUS_MEMSIZE_1M 0x10 +#define CIRRUS_MEMSIZE_2M 0x18 +#define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled. + +// sequencer 0x12 +#define CIRRUS_CURSOR_SHOW 0x01 +#define CIRRUS_CURSOR_HIDDENPEL 0x02 +#define CIRRUS_CURSOR_LARGE 0x04 // 64x64 if set, 32x32 if clear + +// sequencer 0x17 +#define CIRRUS_BUSTYPE_VLBFAST 0x10 +#define CIRRUS_BUSTYPE_PCI 0x20 +#define CIRRUS_BUSTYPE_VLBSLOW 0x30 +#define CIRRUS_BUSTYPE_ISA 0x38 +#define CIRRUS_MMIO_ENABLE 0x04 +#define CIRRUS_MMIO_USE_PCIADDR 0x40 // 0xb8000 if cleared. +#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80 + +// control 0x0b +#define CIRRUS_BANKING_DUAL 0x01 +#define CIRRUS_BANKING_GRANULARITY_16K 0x20 // set:16k, clear:4k + +// control 0x30 +#define CIRRUS_BLTMODE_BACKWARDS 0x01 +#define CIRRUS_BLTMODE_MEMSYSDEST 0x02 +#define CIRRUS_BLTMODE_MEMSYSSRC 0x04 +#define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08 +#define CIRRUS_BLTMODE_PATTERNCOPY 0x40 +#define CIRRUS_BLTMODE_COLOREXPAND 0x80 +#define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30 +#define CIRRUS_BLTMODE_PIXELWIDTH8 0x00 +#define CIRRUS_BLTMODE_PIXELWIDTH16 0x10 +#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20 +#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30 + +// control 0x31 +#define CIRRUS_BLT_BUSY 0x01 +#define CIRRUS_BLT_START 0x02 +#define CIRRUS_BLT_RESET 0x04 +#define CIRRUS_BLT_FIFOUSED 0x10 +#define CIRRUS_BLT_AUTOSTART 0x80 + +// control 0x32 +#define CIRRUS_ROP_0 0x00 +#define CIRRUS_ROP_SRC_AND_DST 0x05 +#define CIRRUS_ROP_NOP 0x06 +#define CIRRUS_ROP_SRC_AND_NOTDST 0x09 +#define CIRRUS_ROP_NOTDST 0x0b +#define CIRRUS_ROP_SRC 0x0d +#define CIRRUS_ROP_1 0x0e +#define CIRRUS_ROP_NOTSRC_AND_DST 0x50 +#define CIRRUS_ROP_SRC_XOR_DST 0x59 +#define CIRRUS_ROP_SRC_OR_DST 0x6d +#define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90 +#define CIRRUS_ROP_SRC_NOTXOR_DST 0x95 +#define CIRRUS_ROP_SRC_OR_NOTDST 0xad +#define CIRRUS_ROP_NOTSRC 0xd0 +#define CIRRUS_ROP_NOTSRC_OR_DST 0xd6 +#define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda + +#define CIRRUS_ROP_NOP_INDEX 2 +#define CIRRUS_ROP_SRC_INDEX 5 + +// control 0x33 +#define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04 +#define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02 +#define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01 + +// memory-mapped IO +#define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword +#define CIRRUS_MMIO_BLTFGCOLOR 0x04 // dword +#define CIRRUS_MMIO_BLTWIDTH 0x08 // word +#define CIRRUS_MMIO_BLTHEIGHT 0x0a // word +#define CIRRUS_MMIO_BLTDESTPITCH 0x0c // word +#define CIRRUS_MMIO_BLTSRCPITCH 0x0e // word +#define CIRRUS_MMIO_BLTDESTADDR 0x10 // dword +#define CIRRUS_MMIO_BLTSRCADDR 0x14 // dword +#define CIRRUS_MMIO_BLTWRITEMASK 0x17 // byte +#define CIRRUS_MMIO_BLTMODE 0x18 // byte +#define CIRRUS_MMIO_BLTROP 0x1a // byte +#define CIRRUS_MMIO_BLTMODEEXT 0x1b // byte +#define CIRRUS_MMIO_BLTTRANSPARENTCOLOR 0x1c // word? +#define CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK 0x20 // word? +#define CIRRUS_MMIO_LINEARDRAW_START_X 0x24 // word +#define CIRRUS_MMIO_LINEARDRAW_START_Y 0x26 // word +#define CIRRUS_MMIO_LINEARDRAW_END_X 0x28 // word +#define CIRRUS_MMIO_LINEARDRAW_END_Y 0x2a // word +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_INC 0x2c // byte +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ROLLOVER 0x2d // byte +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_MASK 0x2e // byte +#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ACCUM 0x2f // byte +#define CIRRUS_MMIO_BRESENHAM_K1 0x30 // word +#define CIRRUS_MMIO_BRESENHAM_K3 0x32 // word +#define CIRRUS_MMIO_BRESENHAM_ERROR 0x34 // word +#define CIRRUS_MMIO_BRESENHAM_DELTA_MAJOR 0x36 // word +#define CIRRUS_MMIO_BRESENHAM_DIRECTION 0x38 // byte +#define CIRRUS_MMIO_LINEDRAW_MODE 0x39 // byte +#define CIRRUS_MMIO_BLTSTATUS 0x40 // byte + +// PCI 0x00: vendor, 0x02: device +#define PCI_VENDOR_CIRRUS 0x1013 +#define PCI_DEVICE_CLGD5462 0x00d0 +#define PCI_DEVICE_CLGD5465 0x00d6 + +// PCI 0x04: command(word), 0x06(word): status +#define PCI_COMMAND_IOACCESS 0x0001 +#define PCI_COMMAND_MEMACCESS 0x0002 +#define PCI_COMMAND_BUSMASTER 0x0004 +#define PCI_COMMAND_SPECIALCYCLE 0x0008 +#define PCI_COMMAND_MEMWRITEINVALID 0x0010 +#define PCI_COMMAND_PALETTESNOOPING 0x0020 +#define PCI_COMMAND_PARITYDETECTION 0x0040 +#define PCI_COMMAND_ADDRESSDATASTEPPING 0x0080 +#define PCI_COMMAND_SERR 0x0100 +#define PCI_COMMAND_BACKTOBACKTRANS 0x0200 +// PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev) +#define PCI_CLASS_BASE_DISPLAY 0x03 +// PCI 0x08, 0x00ff0000 +#define PCI_CLASS_SUB_VGA 0x00 +// PCI 0x0c, 0x00ff0000 (0x0c:cacheline,0x0d:latency,0x0e:headertype,0x0f:Built-in self test) +#define PCI_CLASS_HEADERTYPE_00h 0x00 +// 0x10-0x3f (headertype 00h) +// PCI 0x10,0x14,0x18,0x1c,0x20,0x24: base address mapping registers +// 0x10: MEMBASE, 0x14: IOBASE(hard-coded in XFree86 3.x) +#define PCI_MAP_MEM 0x0 +#define PCI_MAP_IO 0x1 +#define PCI_MAP_MEM_ADDR_MASK (~0xf) +#define PCI_MAP_IO_ADDR_MASK (~0x3) +#define PCI_MAP_MEMFLAGS_32BIT 0x0 +#define PCI_MAP_MEMFLAGS_32BIT_1M 0x1 +#define PCI_MAP_MEMFLAGS_64BIT 0x4 +#define PCI_MAP_MEMFLAGS_CACHEABLE 0x8 +// PCI 0x28: cardbus CIS pointer +// PCI 0x2c: subsystem vendor id, 0x2e: subsystem id +// PCI 0x30: expansion ROM base address +#define PCI_ROMBIOS_ENABLED 0x1 +// PCI 0x34: 0xffffff00=reserved, 0x000000ff=capabilities pointer +// PCI 0x38: reserved +// PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat + +#define CIRRUS_PNPMMIO_SIZE 0x1000 + + +/* I/O and memory hook */ +#define CIRRUS_HOOK_NOT_HANDLED 0 +#define CIRRUS_HOOK_HANDLED 1 + +struct CirrusVGAState; +typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s, + uint8_t * dst, const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight); +typedef void (*cirrus_fill_t)(struct CirrusVGAState *s, + uint8_t *dst, int dst_pitch, int width, int height); + +typedef struct CirrusVGAState { + VGA_STATE_COMMON + + int cirrus_linear_io_addr; + int cirrus_linear_bitblt_io_addr; + int cirrus_mmio_io_addr; + uint32_t cirrus_addr_mask; + uint32_t linear_mmio_mask; + uint8_t cirrus_shadow_gr0; + uint8_t cirrus_shadow_gr1; + uint8_t cirrus_hidden_dac_lockindex; + uint8_t cirrus_hidden_dac_data; + uint32_t cirrus_bank_base[2]; + uint32_t cirrus_bank_limit[2]; + uint8_t cirrus_hidden_palette[48]; + uint32_t hw_cursor_x; + uint32_t hw_cursor_y; + int cirrus_blt_pixelwidth; + int cirrus_blt_width; + int cirrus_blt_height; + int cirrus_blt_dstpitch; + int cirrus_blt_srcpitch; + uint32_t cirrus_blt_fgcol; + uint32_t cirrus_blt_bgcol; + uint32_t cirrus_blt_dstaddr; + uint32_t cirrus_blt_srcaddr; + uint8_t cirrus_blt_mode; + uint8_t cirrus_blt_modeext; + cirrus_bitblt_rop_t cirrus_rop; +#define CIRRUS_BLTBUFSIZE (2048 * 4) /* one line width */ + uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE]; + uint8_t *cirrus_srcptr; + uint8_t *cirrus_srcptr_end; + uint32_t cirrus_srccounter; + /* hwcursor display state */ + int last_hw_cursor_size; + int last_hw_cursor_x; + int last_hw_cursor_y; + int last_hw_cursor_y_start; + int last_hw_cursor_y_end; + int real_vram_size; /* XXX: suppress that */ + CPUWriteMemoryFunc **cirrus_linear_write; +} CirrusVGAState; + +typedef struct PCICirrusVGAState { + PCIDevice dev; + CirrusVGAState cirrus_vga; +} PCICirrusVGAState; + +static uint8_t rop_to_index[256]; + +/*************************************** + * + * prototypes. + * + ***************************************/ + + +static void cirrus_bitblt_reset(CirrusVGAState *s); +static void cirrus_update_memory_access(CirrusVGAState *s); + +/*************************************** + * + * raster operations + * + ***************************************/ + +static void cirrus_bitblt_rop_nop(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ +} + +static void cirrus_bitblt_fill_nop(CirrusVGAState *s, + uint8_t *dst, + int dstpitch, int bltwidth,int bltheight) +{ +} + +#define ROP_NAME 0 +#define ROP_OP(d, s) d = 0 +#include "cirrus_vga_rop.h" + +#define ROP_NAME src_and_dst +#define ROP_OP(d, s) d = (s) & (d) +#include "cirrus_vga_rop.h" + +#define ROP_NAME src_and_notdst +#define ROP_OP(d, s) d = (s) & (~(d)) +#include "cirrus_vga_rop.h" + +#define ROP_NAME notdst +#define ROP_OP(d, s) d = ~(d) +#include "cirrus_vga_rop.h" + +#define ROP_NAME src +#define ROP_OP(d, s) d = s +#include "cirrus_vga_rop.h" + +#define ROP_NAME 1 +#define ROP_OP(d, s) d = ~0 +#include "cirrus_vga_rop.h" + +#define ROP_NAME notsrc_and_dst +#define ROP_OP(d, s) d = (~(s)) & (d) +#include "cirrus_vga_rop.h" + +#define ROP_NAME src_xor_dst +#define ROP_OP(d, s) d = (s) ^ (d) +#include "cirrus_vga_rop.h" + +#define ROP_NAME src_or_dst +#define ROP_OP(d, s) d = (s) | (d) +#include "cirrus_vga_rop.h" + +#define ROP_NAME notsrc_or_notdst +#define ROP_OP(d, s) d = (~(s)) | (~(d)) +#include "cirrus_vga_rop.h" + +#define ROP_NAME src_notxor_dst +#define ROP_OP(d, s) d = ~((s) ^ (d)) +#include "cirrus_vga_rop.h" + +#define ROP_NAME src_or_notdst +#define ROP_OP(d, s) d = (s) | (~(d)) +#include "cirrus_vga_rop.h" + +#define ROP_NAME notsrc +#define ROP_OP(d, s) d = (~(s)) +#include "cirrus_vga_rop.h" + +#define ROP_NAME notsrc_or_dst +#define ROP_OP(d, s) d = (~(s)) | (d) +#include "cirrus_vga_rop.h" + +#define ROP_NAME notsrc_and_notdst +#define ROP_OP(d, s) d = (~(s)) & (~(d)) +#include "cirrus_vga_rop.h" + +static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = { + cirrus_bitblt_rop_fwd_0, + cirrus_bitblt_rop_fwd_src_and_dst, + cirrus_bitblt_rop_nop, + cirrus_bitblt_rop_fwd_src_and_notdst, + cirrus_bitblt_rop_fwd_notdst, + cirrus_bitblt_rop_fwd_src, + cirrus_bitblt_rop_fwd_1, + cirrus_bitblt_rop_fwd_notsrc_and_dst, + cirrus_bitblt_rop_fwd_src_xor_dst, + cirrus_bitblt_rop_fwd_src_or_dst, + cirrus_bitblt_rop_fwd_notsrc_or_notdst, + cirrus_bitblt_rop_fwd_src_notxor_dst, + cirrus_bitblt_rop_fwd_src_or_notdst, + cirrus_bitblt_rop_fwd_notsrc, + cirrus_bitblt_rop_fwd_notsrc_or_dst, + cirrus_bitblt_rop_fwd_notsrc_and_notdst, +}; + +static const cirrus_bitblt_rop_t cirrus_bkwd_rop[16] = { + cirrus_bitblt_rop_bkwd_0, + cirrus_bitblt_rop_bkwd_src_and_dst, + cirrus_bitblt_rop_nop, + cirrus_bitblt_rop_bkwd_src_and_notdst, + cirrus_bitblt_rop_bkwd_notdst, + cirrus_bitblt_rop_bkwd_src, + cirrus_bitblt_rop_bkwd_1, + cirrus_bitblt_rop_bkwd_notsrc_and_dst, + cirrus_bitblt_rop_bkwd_src_xor_dst, + cirrus_bitblt_rop_bkwd_src_or_dst, + cirrus_bitblt_rop_bkwd_notsrc_or_notdst, + cirrus_bitblt_rop_bkwd_src_notxor_dst, + cirrus_bitblt_rop_bkwd_src_or_notdst, + cirrus_bitblt_rop_bkwd_notsrc, + cirrus_bitblt_rop_bkwd_notsrc_or_dst, + cirrus_bitblt_rop_bkwd_notsrc_and_notdst, +}; + +#define ROP2(name) {\ + name ## _8,\ + name ## _16,\ + name ## _24,\ + name ## _32,\ + } + +#define ROP_NOP2(func) {\ + func,\ + func,\ + func,\ + func,\ + } + +static const cirrus_bitblt_rop_t cirrus_patternfill[16][4] = { + ROP2(cirrus_patternfill_0), + ROP2(cirrus_patternfill_src_and_dst), + ROP_NOP2(cirrus_bitblt_rop_nop), + ROP2(cirrus_patternfill_src_and_notdst), + ROP2(cirrus_patternfill_notdst), + ROP2(cirrus_patternfill_src), + ROP2(cirrus_patternfill_1), + ROP2(cirrus_patternfill_notsrc_and_dst), + ROP2(cirrus_patternfill_src_xor_dst), + ROP2(cirrus_patternfill_src_or_dst), + ROP2(cirrus_patternfill_notsrc_or_notdst), + ROP2(cirrus_patternfill_src_notxor_dst), + ROP2(cirrus_patternfill_src_or_notdst), + ROP2(cirrus_patternfill_notsrc), + ROP2(cirrus_patternfill_notsrc_or_dst), + ROP2(cirrus_patternfill_notsrc_and_notdst), +}; + +static const cirrus_bitblt_rop_t cirrus_colorexpand_transp[16][4] = { + ROP2(cirrus_colorexpand_transp_0), + ROP2(cirrus_colorexpand_transp_src_and_dst), + ROP_NOP2(cirrus_bitblt_rop_nop), + ROP2(cirrus_colorexpand_transp_src_and_notdst), + ROP2(cirrus_colorexpand_transp_notdst), + ROP2(cirrus_colorexpand_transp_src), + ROP2(cirrus_colorexpand_transp_1), + ROP2(cirrus_colorexpand_transp_notsrc_and_dst), + ROP2(cirrus_colorexpand_transp_src_xor_dst), + ROP2(cirrus_colorexpand_transp_src_or_dst), + ROP2(cirrus_colorexpand_transp_notsrc_or_notdst), + ROP2(cirrus_colorexpand_transp_src_notxor_dst), + ROP2(cirrus_colorexpand_transp_src_or_notdst), + ROP2(cirrus_colorexpand_transp_notsrc), + ROP2(cirrus_colorexpand_transp_notsrc_or_dst), + ROP2(cirrus_colorexpand_transp_notsrc_and_notdst), +}; + +static const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = { + ROP2(cirrus_colorexpand_0), + ROP2(cirrus_colorexpand_src_and_dst), + ROP_NOP2(cirrus_bitblt_rop_nop), + ROP2(cirrus_colorexpand_src_and_notdst), + ROP2(cirrus_colorexpand_notdst), + ROP2(cirrus_colorexpand_src), + ROP2(cirrus_colorexpand_1), + ROP2(cirrus_colorexpand_notsrc_and_dst), + ROP2(cirrus_colorexpand_src_xor_dst), + ROP2(cirrus_colorexpand_src_or_dst), + ROP2(cirrus_colorexpand_notsrc_or_notdst), + ROP2(cirrus_colorexpand_src_notxor_dst), + ROP2(cirrus_colorexpand_src_or_notdst), + ROP2(cirrus_colorexpand_notsrc), + ROP2(cirrus_colorexpand_notsrc_or_dst), + ROP2(cirrus_colorexpand_notsrc_and_notdst), +}; + +static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern_transp[16][4] = { + ROP2(cirrus_colorexpand_pattern_transp_0), + ROP2(cirrus_colorexpand_pattern_transp_src_and_dst), + ROP_NOP2(cirrus_bitblt_rop_nop), + ROP2(cirrus_colorexpand_pattern_transp_src_and_notdst), + ROP2(cirrus_colorexpand_pattern_transp_notdst), + ROP2(cirrus_colorexpand_pattern_transp_src), + ROP2(cirrus_colorexpand_pattern_transp_1), + ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_dst), + ROP2(cirrus_colorexpand_pattern_transp_src_xor_dst), + ROP2(cirrus_colorexpand_pattern_transp_src_or_dst), + ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_notdst), + ROP2(cirrus_colorexpand_pattern_transp_src_notxor_dst), + ROP2(cirrus_colorexpand_pattern_transp_src_or_notdst), + ROP2(cirrus_colorexpand_pattern_transp_notsrc), + ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_dst), + ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_notdst), +}; + +static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern[16][4] = { + ROP2(cirrus_colorexpand_pattern_0), + ROP2(cirrus_colorexpand_pattern_src_and_dst), + ROP_NOP2(cirrus_bitblt_rop_nop), + ROP2(cirrus_colorexpand_pattern_src_and_notdst), + ROP2(cirrus_colorexpand_pattern_notdst), + ROP2(cirrus_colorexpand_pattern_src), + ROP2(cirrus_colorexpand_pattern_1), + ROP2(cirrus_colorexpand_pattern_notsrc_and_dst), + ROP2(cirrus_colorexpand_pattern_src_xor_dst), + ROP2(cirrus_colorexpand_pattern_src_or_dst), + ROP2(cirrus_colorexpand_pattern_notsrc_or_notdst), + ROP2(cirrus_colorexpand_pattern_src_notxor_dst), + ROP2(cirrus_colorexpand_pattern_src_or_notdst), + ROP2(cirrus_colorexpand_pattern_notsrc), + ROP2(cirrus_colorexpand_pattern_notsrc_or_dst), + ROP2(cirrus_colorexpand_pattern_notsrc_and_notdst), +}; + +static const cirrus_fill_t cirrus_fill[16][4] = { + ROP2(cirrus_fill_0), + ROP2(cirrus_fill_src_and_dst), + ROP_NOP2(cirrus_bitblt_fill_nop), + ROP2(cirrus_fill_src_and_notdst), + ROP2(cirrus_fill_notdst), + ROP2(cirrus_fill_src), + ROP2(cirrus_fill_1), + ROP2(cirrus_fill_notsrc_and_dst), + ROP2(cirrus_fill_src_xor_dst), + ROP2(cirrus_fill_src_or_dst), + ROP2(cirrus_fill_notsrc_or_notdst), + ROP2(cirrus_fill_src_notxor_dst), + ROP2(cirrus_fill_src_or_notdst), + ROP2(cirrus_fill_notsrc), + ROP2(cirrus_fill_notsrc_or_dst), + ROP2(cirrus_fill_notsrc_and_notdst), +}; + +static inline void cirrus_bitblt_fgcol(CirrusVGAState *s) +{ + unsigned int color; + switch (s->cirrus_blt_pixelwidth) { + case 1: + s->cirrus_blt_fgcol = s->cirrus_shadow_gr1; + break; + case 2: + color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8); + s->cirrus_blt_fgcol = le16_to_cpu(color); + break; + case 3: + s->cirrus_blt_fgcol = s->cirrus_shadow_gr1 | + (s->gr[0x11] << 8) | (s->gr[0x13] << 16); + break; + default: + case 4: + color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8) | + (s->gr[0x13] << 16) | (s->gr[0x15] << 24); + s->cirrus_blt_fgcol = le32_to_cpu(color); + break; + } +} + +static inline void cirrus_bitblt_bgcol(CirrusVGAState *s) +{ + unsigned int color; + switch (s->cirrus_blt_pixelwidth) { + case 1: + s->cirrus_blt_bgcol = s->cirrus_shadow_gr0; + break; + case 2: + color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8); + s->cirrus_blt_bgcol = le16_to_cpu(color); + break; + case 3: + s->cirrus_blt_bgcol = s->cirrus_shadow_gr0 | + (s->gr[0x10] << 8) | (s->gr[0x12] << 16); + break; + default: + case 4: + color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8) | + (s->gr[0x12] << 16) | (s->gr[0x14] << 24); + s->cirrus_blt_bgcol = le32_to_cpu(color); + break; + } +} + +static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin, + int off_pitch, int bytesperline, + int lines) +{ + int y; + int off_cur; + int off_cur_end; + + for (y = 0; y < lines; y++) { + off_cur = off_begin; + off_cur_end = off_cur + bytesperline; + off_cur &= TARGET_PAGE_MASK; + while (off_cur < off_cur_end) { + cpu_physical_memory_set_dirty(s->vram_offset + off_cur); + off_cur += TARGET_PAGE_SIZE; + } + off_begin += off_pitch; + } +} + +static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, + const uint8_t * src) +{ + uint8_t *dst; + + dst = s->vram_ptr + s->cirrus_blt_dstaddr; + (*s->cirrus_rop) (s, dst, src, + s->cirrus_blt_dstpitch, 0, + s->cirrus_blt_width, s->cirrus_blt_height); + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, + s->cirrus_blt_dstpitch, s->cirrus_blt_width, + s->cirrus_blt_height); + return 1; +} + +/* fill */ + +static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop) +{ + cirrus_fill_t rop_func; + + rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; + rop_func(s, s->vram_ptr + s->cirrus_blt_dstaddr, + s->cirrus_blt_dstpitch, + s->cirrus_blt_width, s->cirrus_blt_height); + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, + s->cirrus_blt_dstpitch, s->cirrus_blt_width, + s->cirrus_blt_height); + cirrus_bitblt_reset(s); + return 1; +} + +/*************************************** + * + * bitblt (video-to-video) + * + ***************************************/ + +static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s) +{ + return cirrus_bitblt_common_patterncopy(s, + s->vram_ptr + + (s->cirrus_blt_srcaddr & ~7)); +} + +static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s) +{ + (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr, + s->vram_ptr + s->cirrus_blt_srcaddr, + s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, + s->cirrus_blt_width, s->cirrus_blt_height); + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, + s->cirrus_blt_dstpitch, s->cirrus_blt_width, + s->cirrus_blt_height); + return 1; +} + +/*************************************** + * + * bitblt (cpu-to-video) + * + ***************************************/ + +static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s) +{ + int copy_count; + uint8_t *end_ptr; + + if (s->cirrus_srccounter > 0) { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { + cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf); + the_end: + s->cirrus_srccounter = 0; + cirrus_bitblt_reset(s); + } else { + /* at least one scan line */ + do { + (*s->cirrus_rop)(s, s->vram_ptr + s->cirrus_blt_dstaddr, + s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1); + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0, + s->cirrus_blt_width, 1); + s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch; + s->cirrus_srccounter -= s->cirrus_blt_srcpitch; + if (s->cirrus_srccounter <= 0) + goto the_end; + /* more bytes than needed can be transfered because of + word alignment, so we keep them for the next line */ + /* XXX: keep alignment to speed up transfer */ + end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; + copy_count = s->cirrus_srcptr_end - end_ptr; + memmove(s->cirrus_bltbuf, end_ptr, copy_count); + s->cirrus_srcptr = s->cirrus_bltbuf + copy_count; + s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; + } while (s->cirrus_srcptr >= s->cirrus_srcptr_end); + } + } +} + +/*************************************** + * + * bitblt wrapper + * + ***************************************/ + +static void cirrus_bitblt_reset(CirrusVGAState * s) +{ + s->gr[0x31] &= + ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED); + s->cirrus_srcptr = &s->cirrus_bltbuf[0]; + s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; + s->cirrus_srccounter = 0; + cirrus_update_memory_access(s); +} + +static int cirrus_bitblt_cputovideo(CirrusVGAState * s) +{ + int w; + + s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC; + s->cirrus_srcptr = &s->cirrus_bltbuf[0]; + s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; + + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { + s->cirrus_blt_srcpitch = 8; + } else { + /* XXX: check for 24 bpp */ + s->cirrus_blt_srcpitch = 8 * 8 * s->cirrus_blt_pixelwidth; + } + s->cirrus_srccounter = s->cirrus_blt_srcpitch; + } else { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { + w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth; + if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) + s->cirrus_blt_srcpitch = ((w + 31) >> 5); + else + s->cirrus_blt_srcpitch = ((w + 7) >> 3); + } else { + s->cirrus_blt_srcpitch = s->cirrus_blt_width; + } + s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height; + } + s->cirrus_srcptr = s->cirrus_bltbuf; + s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; + cirrus_update_memory_access(s); + return 1; +} + +static int cirrus_bitblt_videotocpu(CirrusVGAState * s) +{ + /* XXX */ +#ifdef DEBUG_BITBLT + printf("cirrus: bitblt (video to cpu) is not implemented yet\n"); +#endif + return 0; +} + +static int cirrus_bitblt_videotovideo(CirrusVGAState * s) +{ + int ret; + + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { + ret = cirrus_bitblt_videotovideo_patterncopy(s); + } else { + ret = cirrus_bitblt_videotovideo_copy(s); + } + if (ret) + cirrus_bitblt_reset(s); + return ret; +} + +static void cirrus_bitblt_start(CirrusVGAState * s) +{ + uint8_t blt_rop; + + s->gr[0x31] |= CIRRUS_BLT_BUSY; + + s->cirrus_blt_width = (s->gr[0x20] | (s->gr[0x21] << 8)) + 1; + s->cirrus_blt_height = (s->gr[0x22] | (s->gr[0x23] << 8)) + 1; + s->cirrus_blt_dstpitch = (s->gr[0x24] | (s->gr[0x25] << 8)); + s->cirrus_blt_srcpitch = (s->gr[0x26] | (s->gr[0x27] << 8)); + s->cirrus_blt_dstaddr = + (s->gr[0x28] | (s->gr[0x29] << 8) | (s->gr[0x2a] << 16)); + s->cirrus_blt_srcaddr = + (s->gr[0x2c] | (s->gr[0x2d] << 8) | (s->gr[0x2e] << 16)); + s->cirrus_blt_mode = s->gr[0x30]; + s->cirrus_blt_modeext = s->gr[0x33]; + blt_rop = s->gr[0x32]; + +#ifdef DEBUG_BITBLT + printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spicth=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n", + blt_rop, + s->cirrus_blt_mode, + s->cirrus_blt_modeext, + s->cirrus_blt_width, + s->cirrus_blt_height, + s->cirrus_blt_dstpitch, + s->cirrus_blt_srcpitch, + s->cirrus_blt_dstaddr, + s->cirrus_blt_srcaddr, + s->sr[0x2f]); +#endif + + switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { + case CIRRUS_BLTMODE_PIXELWIDTH8: + s->cirrus_blt_pixelwidth = 1; + break; + case CIRRUS_BLTMODE_PIXELWIDTH16: + s->cirrus_blt_pixelwidth = 2; + break; + case CIRRUS_BLTMODE_PIXELWIDTH24: + s->cirrus_blt_pixelwidth = 3; + break; + case CIRRUS_BLTMODE_PIXELWIDTH32: + s->cirrus_blt_pixelwidth = 4; + break; + default: +#ifdef DEBUG_BITBLT + printf("cirrus: bitblt - pixel width is unknown\n"); +#endif + goto bitblt_ignore; + } + s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK; + + if ((s-> + cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC | + CIRRUS_BLTMODE_MEMSYSDEST)) + == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) { +#ifdef DEBUG_BITBLT + printf("cirrus: bitblt - memory-to-memory copy is requested\n"); +#endif + goto bitblt_ignore; + } + + if ((s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) && + (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST | + CIRRUS_BLTMODE_TRANSPARENTCOMP | + CIRRUS_BLTMODE_PATTERNCOPY | + CIRRUS_BLTMODE_COLOREXPAND)) == + (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) { + cirrus_bitblt_fgcol(s); + cirrus_bitblt_solidfill(s, blt_rop); + } else { + if ((s->cirrus_blt_mode & (CIRRUS_BLTMODE_COLOREXPAND | + CIRRUS_BLTMODE_PATTERNCOPY)) == + CIRRUS_BLTMODE_COLOREXPAND) { + + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { + if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) + cirrus_bitblt_bgcol(s); + else + cirrus_bitblt_fgcol(s); + s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; + } else { + cirrus_bitblt_fgcol(s); + cirrus_bitblt_bgcol(s); + s->cirrus_rop = cirrus_colorexpand[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; + } + } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { + if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) + cirrus_bitblt_bgcol(s); + else + cirrus_bitblt_fgcol(s); + s->cirrus_rop = cirrus_colorexpand_pattern_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; + } else { + cirrus_bitblt_fgcol(s); + cirrus_bitblt_bgcol(s); + s->cirrus_rop = cirrus_colorexpand_pattern[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; + } + } else { + s->cirrus_rop = cirrus_patternfill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; + } + } else { + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) { + s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch; + s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch; + s->cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]]; + } else { + s->cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]]; + } + } + + // setup bitblt engine. + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) { + if (!cirrus_bitblt_cputovideo(s)) + goto bitblt_ignore; + } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) { + if (!cirrus_bitblt_videotocpu(s)) + goto bitblt_ignore; + } else { + if (!cirrus_bitblt_videotovideo(s)) + goto bitblt_ignore; + } + } + return; + bitblt_ignore:; + cirrus_bitblt_reset(s); +} + +static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value) +{ + unsigned old_value; + + old_value = s->gr[0x31]; + s->gr[0x31] = reg_value; + + if (((old_value & CIRRUS_BLT_RESET) != 0) && + ((reg_value & CIRRUS_BLT_RESET) == 0)) { + cirrus_bitblt_reset(s); + } else if (((old_value & CIRRUS_BLT_START) == 0) && + ((reg_value & CIRRUS_BLT_START) != 0)) { + cirrus_bitblt_start(s); + } +} + + +/*************************************** + * + * basic parameters + * + ***************************************/ + +static void cirrus_get_offsets(VGAState *s1, + uint32_t *pline_offset, + uint32_t *pstart_addr) +{ + CirrusVGAState * s = (CirrusVGAState *)s1; + uint32_t start_addr; + uint32_t line_offset; + + line_offset = s->cr[0x13] + | ((s->cr[0x1b] & 0x10) << 4); + line_offset <<= 3; + *pline_offset = line_offset; + + start_addr = (s->cr[0x0c] << 8) + | s->cr[0x0d] + | ((s->cr[0x1b] & 0x01) << 16) + | ((s->cr[0x1b] & 0x0c) << 15) + | ((s->cr[0x1d] & 0x80) << 12); + *pstart_addr = start_addr; +} + +static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s) +{ + uint32_t ret = 16; + + switch (s->cirrus_hidden_dac_data & 0xf) { + case 0: + ret = 15; + break; /* Sierra HiColor */ + case 1: + ret = 16; + break; /* XGA HiColor */ + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: invalid DAC value %x in 16bpp\n", + (s->cirrus_hidden_dac_data & 0xf)); +#endif + ret = 15; /* XXX */ + break; + } + return ret; +} + +static int cirrus_get_bpp(VGAState *s1) +{ + CirrusVGAState * s = (CirrusVGAState *)s1; + uint32_t ret = 8; + + if ((s->sr[0x07] & 0x01) != 0) { + /* Cirrus SVGA */ + switch (s->sr[0x07] & CIRRUS_SR7_BPP_MASK) { + case CIRRUS_SR7_BPP_8: + ret = 8; + break; + case CIRRUS_SR7_BPP_16_DOUBLEVCLK: + ret = cirrus_get_bpp16_depth(s); + break; + case CIRRUS_SR7_BPP_24: + ret = 24; + break; + case CIRRUS_SR7_BPP_16: + ret = cirrus_get_bpp16_depth(s); + break; + case CIRRUS_SR7_BPP_32: + ret = 32; + break; + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: unknown bpp - sr7=%x\n", s->sr[0x7]); +#endif + ret = 8; + break; + } + } else { + /* VGA */ + ret = 0; + } + + return ret; +} + +static void cirrus_get_resolution(VGAState *s, int *pwidth, int *pheight) +{ + int width, height; + + width = (s->cr[0x01] + 1) * 8; + height = s->cr[0x12] | + ((s->cr[0x07] & 0x02) << 7) | + ((s->cr[0x07] & 0x40) << 3); + height = (height + 1); + /* interlace support */ + if (s->cr[0x1a] & 0x01) + height = height * 2; + *pwidth = width; + *pheight = height; +} + +/*************************************** + * + * bank memory + * + ***************************************/ + +static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index) +{ + unsigned offset; + unsigned limit; + + if ((s->gr[0x0b] & 0x01) != 0) /* dual bank */ + offset = s->gr[0x09 + bank_index]; + else /* single bank */ + offset = s->gr[0x09]; + + if ((s->gr[0x0b] & 0x20) != 0) + offset <<= 14; + else + offset <<= 12; + + if (s->vram_size <= offset) + limit = 0; + else + limit = s->vram_size - offset; + + if (((s->gr[0x0b] & 0x01) == 0) && (bank_index != 0)) { + if (limit > 0x8000) { + offset += 0x8000; + limit -= 0x8000; + } else { + limit = 0; + } + } + + if (limit > 0) { + s->cirrus_bank_base[bank_index] = offset; + s->cirrus_bank_limit[bank_index] = limit; + } else { + s->cirrus_bank_base[bank_index] = 0; + s->cirrus_bank_limit[bank_index] = 0; + } +} + +/*************************************** + * + * I/O access between 0x3c4-0x3c5 + * + ***************************************/ + +static int +cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value) +{ + switch (reg_index) { + case 0x00: // Standard VGA + case 0x01: // Standard VGA + case 0x02: // Standard VGA + case 0x03: // Standard VGA + case 0x04: // Standard VGA + return CIRRUS_HOOK_NOT_HANDLED; + case 0x06: // Unlock Cirrus extensions + *reg_value = s->sr[reg_index]; + break; + case 0x10: + case 0x30: + case 0x50: + case 0x70: // Graphics Cursor X + case 0x90: + case 0xb0: + case 0xd0: + case 0xf0: // Graphics Cursor X + *reg_value = s->sr[0x10]; + break; + case 0x11: + case 0x31: + case 0x51: + case 0x71: // Graphics Cursor Y + case 0x91: + case 0xb1: + case 0xd1: + case 0xf1: // Graphics Cursor Y + *reg_value = s->sr[0x11]; + break; + case 0x05: // ??? + case 0x07: // Extended Sequencer Mode + case 0x08: // EEPROM Control + case 0x09: // Scratch Register 0 + case 0x0a: // Scratch Register 1 + case 0x0b: // VCLK 0 + case 0x0c: // VCLK 1 + case 0x0d: // VCLK 2 + case 0x0e: // VCLK 3 + case 0x0f: // DRAM Control + case 0x12: // Graphics Cursor Attribute + case 0x13: // Graphics Cursor Pattern Address + case 0x14: // Scratch Register 2 + case 0x15: // Scratch Register 3 + case 0x16: // Performance Tuning Register + case 0x17: // Configuration Readback and Extended Control + case 0x18: // Signature Generator Control + case 0x19: // Signal Generator Result + case 0x1a: // Signal Generator Result + case 0x1b: // VCLK 0 Denominator & Post + case 0x1c: // VCLK 1 Denominator & Post + case 0x1d: // VCLK 2 Denominator & Post + case 0x1e: // VCLK 3 Denominator & Post + case 0x1f: // BIOS Write Enable and MCLK select +#ifdef DEBUG_CIRRUS + printf("cirrus: handled inport sr_index %02x\n", reg_index); +#endif + *reg_value = s->sr[reg_index]; + break; + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: inport sr_index %02x\n", reg_index); +#endif + *reg_value = 0xff; + break; + } + + return CIRRUS_HOOK_HANDLED; +} + +static int +cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value) +{ + switch (reg_index) { + case 0x00: // Standard VGA + case 0x01: // Standard VGA + case 0x02: // Standard VGA + case 0x03: // Standard VGA + case 0x04: // Standard VGA + return CIRRUS_HOOK_NOT_HANDLED; + case 0x06: // Unlock Cirrus extensions + reg_value &= 0x17; + if (reg_value == 0x12) { + s->sr[reg_index] = 0x12; + } else { + s->sr[reg_index] = 0x0f; + } + break; + case 0x10: + case 0x30: + case 0x50: + case 0x70: // Graphics Cursor X + case 0x90: + case 0xb0: + case 0xd0: + case 0xf0: // Graphics Cursor X + s->sr[0x10] = reg_value; + s->hw_cursor_x = (reg_value << 3) | (reg_index >> 5); + break; + case 0x11: + case 0x31: + case 0x51: + case 0x71: // Graphics Cursor Y + case 0x91: + case 0xb1: + case 0xd1: + case 0xf1: // Graphics Cursor Y + s->sr[0x11] = reg_value; + s->hw_cursor_y = (reg_value << 3) | (reg_index >> 5); + break; + case 0x07: // Extended Sequencer Mode + case 0x08: // EEPROM Control + case 0x09: // Scratch Register 0 + case 0x0a: // Scratch Register 1 + case 0x0b: // VCLK 0 + case 0x0c: // VCLK 1 + case 0x0d: // VCLK 2 + case 0x0e: // VCLK 3 + case 0x0f: // DRAM Control + case 0x12: // Graphics Cursor Attribute + case 0x13: // Graphics Cursor Pattern Address + case 0x14: // Scratch Register 2 + case 0x15: // Scratch Register 3 + case 0x16: // Performance Tuning Register + case 0x18: // Signature Generator Control + case 0x19: // Signature Generator Result + case 0x1a: // Signature Generator Result + case 0x1b: // VCLK 0 Denominator & Post + case 0x1c: // VCLK 1 Denominator & Post + case 0x1d: // VCLK 2 Denominator & Post + case 0x1e: // VCLK 3 Denominator & Post + case 0x1f: // BIOS Write Enable and MCLK select + s->sr[reg_index] = reg_value; +#ifdef DEBUG_CIRRUS + printf("cirrus: handled outport sr_index %02x, sr_value %02x\n", + reg_index, reg_value); +#endif + break; + case 0x17: // Configuration Readback and Extended Control + s->sr[reg_index] = reg_value; + cirrus_update_memory_access(s); + break; + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: outport sr_index %02x, sr_value %02x\n", reg_index, + reg_value); +#endif + break; + } + + return CIRRUS_HOOK_HANDLED; +} + +/*************************************** + * + * I/O access at 0x3c6 + * + ***************************************/ + +static void cirrus_read_hidden_dac(CirrusVGAState * s, int *reg_value) +{ + *reg_value = 0xff; + if (++s->cirrus_hidden_dac_lockindex == 5) { + *reg_value = s->cirrus_hidden_dac_data; + s->cirrus_hidden_dac_lockindex = 0; + } +} + +static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value) +{ + if (s->cirrus_hidden_dac_lockindex == 4) { + s->cirrus_hidden_dac_data = reg_value; +#if defined(DEBUG_CIRRUS) + printf("cirrus: outport hidden DAC, value %02x\n", reg_value); +#endif + } + s->cirrus_hidden_dac_lockindex = 0; +} + +/*************************************** + * + * I/O access at 0x3c9 + * + ***************************************/ + +static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value) +{ + if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL)) + return CIRRUS_HOOK_NOT_HANDLED; + *reg_value = + s->cirrus_hidden_palette[(s->dac_read_index & 0x0f) * 3 + + s->dac_sub_index]; + if (++s->dac_sub_index == 3) { + s->dac_sub_index = 0; + s->dac_read_index++; + } + return CIRRUS_HOOK_HANDLED; +} + +static int cirrus_hook_write_palette(CirrusVGAState * s, int reg_value) +{ + if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL)) + return CIRRUS_HOOK_NOT_HANDLED; + s->dac_cache[s->dac_sub_index] = reg_value; + if (++s->dac_sub_index == 3) { + memcpy(&s->cirrus_hidden_palette[(s->dac_write_index & 0x0f) * 3], + s->dac_cache, 3); + /* XXX update cursor */ + s->dac_sub_index = 0; + s->dac_write_index++; + } + return CIRRUS_HOOK_HANDLED; +} + +/*************************************** + * + * I/O access between 0x3ce-0x3cf + * + ***************************************/ + +static int +cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value) +{ + switch (reg_index) { + case 0x00: // Standard VGA, BGCOLOR 0x000000ff + *reg_value = s->cirrus_shadow_gr0; + return CIRRUS_HOOK_HANDLED; + case 0x01: // Standard VGA, FGCOLOR 0x000000ff + *reg_value = s->cirrus_shadow_gr1; + return CIRRUS_HOOK_HANDLED; + case 0x02: // Standard VGA + case 0x03: // Standard VGA + case 0x04: // Standard VGA + case 0x06: // Standard VGA + case 0x07: // Standard VGA + case 0x08: // Standard VGA + return CIRRUS_HOOK_NOT_HANDLED; + case 0x05: // Standard VGA, Cirrus extended mode + default: + break; + } + + if (reg_index < 0x3a) { + *reg_value = s->gr[reg_index]; + } else { +#ifdef DEBUG_CIRRUS + printf("cirrus: inport gr_index %02x\n", reg_index); +#endif + *reg_value = 0xff; + } + + return CIRRUS_HOOK_HANDLED; +} + +static int +cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) +{ +#if defined(DEBUG_BITBLT) && 0 + printf("gr%02x: %02x\n", reg_index, reg_value); +#endif + switch (reg_index) { + case 0x00: // Standard VGA, BGCOLOR 0x000000ff + s->cirrus_shadow_gr0 = reg_value; + return CIRRUS_HOOK_NOT_HANDLED; + case 0x01: // Standard VGA, FGCOLOR 0x000000ff + s->cirrus_shadow_gr1 = reg_value; + return CIRRUS_HOOK_NOT_HANDLED; + case 0x02: // Standard VGA + case 0x03: // Standard VGA + case 0x04: // Standard VGA + case 0x06: // Standard VGA + case 0x07: // Standard VGA + case 0x08: // Standard VGA + return CIRRUS_HOOK_NOT_HANDLED; + case 0x05: // Standard VGA, Cirrus extended mode + s->gr[reg_index] = reg_value & 0x7f; + cirrus_update_memory_access(s); + break; + case 0x09: // bank offset #0 + case 0x0A: // bank offset #1 + s->gr[reg_index] = reg_value; + cirrus_update_bank_ptr(s, 0); + cirrus_update_bank_ptr(s, 1); + break; + case 0x0B: + s->gr[reg_index] = reg_value; + cirrus_update_bank_ptr(s, 0); + cirrus_update_bank_ptr(s, 1); + cirrus_update_memory_access(s); + break; + case 0x10: // BGCOLOR 0x0000ff00 + case 0x11: // FGCOLOR 0x0000ff00 + case 0x12: // BGCOLOR 0x00ff0000 + case 0x13: // FGCOLOR 0x00ff0000 + case 0x14: // BGCOLOR 0xff000000 + case 0x15: // FGCOLOR 0xff000000 + case 0x20: // BLT WIDTH 0x0000ff + case 0x22: // BLT HEIGHT 0x0000ff + case 0x24: // BLT DEST PITCH 0x0000ff + case 0x26: // BLT SRC PITCH 0x0000ff + case 0x28: // BLT DEST ADDR 0x0000ff + case 0x29: // BLT DEST ADDR 0x00ff00 + case 0x2c: // BLT SRC ADDR 0x0000ff + case 0x2d: // BLT SRC ADDR 0x00ff00 + case 0x2f: // BLT WRITEMASK + case 0x30: // BLT MODE + case 0x32: // RASTER OP + case 0x33: // BLT MODEEXT + case 0x34: // BLT TRANSPARENT COLOR 0x00ff + case 0x35: // BLT TRANSPARENT COLOR 0xff00 + case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff + case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00 + s->gr[reg_index] = reg_value; + break; + case 0x21: // BLT WIDTH 0x001f00 + case 0x23: // BLT HEIGHT 0x001f00 + case 0x25: // BLT DEST PITCH 0x001f00 + case 0x27: // BLT SRC PITCH 0x001f00 + s->gr[reg_index] = reg_value & 0x1f; + break; + case 0x2a: // BLT DEST ADDR 0x3f0000 + s->gr[reg_index] = reg_value & 0x3f; + /* if auto start mode, starts bit blt now */ + if (s->gr[0x31] & CIRRUS_BLT_AUTOSTART) { + cirrus_bitblt_start(s); + } + break; + case 0x2e: // BLT SRC ADDR 0x3f0000 + s->gr[reg_index] = reg_value & 0x3f; + break; + case 0x31: // BLT STATUS/START + cirrus_write_bitblt(s, reg_value); + break; + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index, + reg_value); +#endif + break; + } + + return CIRRUS_HOOK_HANDLED; +} + +/*************************************** + * + * I/O access between 0x3d4-0x3d5 + * + ***************************************/ + +static int +cirrus_hook_read_cr(CirrusVGAState * s, unsigned reg_index, int *reg_value) +{ + switch (reg_index) { + case 0x00: // Standard VGA + case 0x01: // Standard VGA + case 0x02: // Standard VGA + case 0x03: // Standard VGA + case 0x04: // Standard VGA + case 0x05: // Standard VGA + case 0x06: // Standard VGA + case 0x07: // Standard VGA + case 0x08: // Standard VGA + case 0x09: // Standard VGA + case 0x0a: // Standard VGA + case 0x0b: // Standard VGA + case 0x0c: // Standard VGA + case 0x0d: // Standard VGA + case 0x0e: // Standard VGA + case 0x0f: // Standard VGA + case 0x10: // Standard VGA + case 0x11: // Standard VGA + case 0x12: // Standard VGA + case 0x13: // Standard VGA + case 0x14: // Standard VGA + case 0x15: // Standard VGA + case 0x16: // Standard VGA + case 0x17: // Standard VGA + case 0x18: // Standard VGA + return CIRRUS_HOOK_NOT_HANDLED; + case 0x19: // Interlace End + case 0x1a: // Miscellaneous Control + case 0x1b: // Extended Display Control + case 0x1c: // Sync Adjust and Genlock + case 0x1d: // Overlay Extended Control + case 0x22: // Graphics Data Latches Readback (R) + case 0x24: // Attribute Controller Toggle Readback (R) + case 0x25: // Part Status + case 0x27: // Part ID (R) + *reg_value = s->cr[reg_index]; + break; + case 0x26: // Attribute Controller Index Readback (R) + *reg_value = s->ar_index & 0x3f; + break; + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: inport cr_index %02x\n", reg_index); + *reg_value = 0xff; +#endif + break; + } + + return CIRRUS_HOOK_HANDLED; +} + +static int +cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value) +{ + switch (reg_index) { + case 0x00: // Standard VGA + case 0x01: // Standard VGA + case 0x02: // Standard VGA + case 0x03: // Standard VGA + case 0x04: // Standard VGA + case 0x05: // Standard VGA + case 0x06: // Standard VGA + case 0x07: // Standard VGA + case 0x08: // Standard VGA + case 0x09: // Standard VGA + case 0x0a: // Standard VGA + case 0x0b: // Standard VGA + case 0x0c: // Standard VGA + case 0x0d: // Standard VGA + case 0x0e: // Standard VGA + case 0x0f: // Standard VGA + case 0x10: // Standard VGA + case 0x11: // Standard VGA + case 0x12: // Standard VGA + case 0x13: // Standard VGA + case 0x14: // Standard VGA + case 0x15: // Standard VGA + case 0x16: // Standard VGA + case 0x17: // Standard VGA + case 0x18: // Standard VGA + return CIRRUS_HOOK_NOT_HANDLED; + case 0x19: // Interlace End + case 0x1a: // Miscellaneous Control + case 0x1b: // Extended Display Control + case 0x1c: // Sync Adjust and Genlock + case 0x1d: // Overlay Extended Control + s->cr[reg_index] = reg_value; +#ifdef DEBUG_CIRRUS + printf("cirrus: handled outport cr_index %02x, cr_value %02x\n", + reg_index, reg_value); +#endif + break; + case 0x22: // Graphics Data Latches Readback (R) + case 0x24: // Attribute Controller Toggle Readback (R) + case 0x26: // Attribute Controller Index Readback (R) + case 0x27: // Part ID (R) + break; + case 0x25: // Part Status + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: outport cr_index %02x, cr_value %02x\n", reg_index, + reg_value); +#endif + break; + } + + return CIRRUS_HOOK_HANDLED; +} + +/*************************************** + * + * memory-mapped I/O (bitblt) + * + ***************************************/ + +static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address) +{ + int value = 0xff; + + switch (address) { + case (CIRRUS_MMIO_BLTBGCOLOR + 0): + cirrus_hook_read_gr(s, 0x00, &value); + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 1): + cirrus_hook_read_gr(s, 0x10, &value); + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 2): + cirrus_hook_read_gr(s, 0x12, &value); + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 3): + cirrus_hook_read_gr(s, 0x14, &value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 0): + cirrus_hook_read_gr(s, 0x01, &value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 1): + cirrus_hook_read_gr(s, 0x11, &value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 2): + cirrus_hook_read_gr(s, 0x13, &value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 3): + cirrus_hook_read_gr(s, 0x15, &value); + break; + case (CIRRUS_MMIO_BLTWIDTH + 0): + cirrus_hook_read_gr(s, 0x20, &value); + break; + case (CIRRUS_MMIO_BLTWIDTH + 1): + cirrus_hook_read_gr(s, 0x21, &value); + break; + case (CIRRUS_MMIO_BLTHEIGHT + 0): + cirrus_hook_read_gr(s, 0x22, &value); + break; + case (CIRRUS_MMIO_BLTHEIGHT + 1): + cirrus_hook_read_gr(s, 0x23, &value); + break; + case (CIRRUS_MMIO_BLTDESTPITCH + 0): + cirrus_hook_read_gr(s, 0x24, &value); + break; + case (CIRRUS_MMIO_BLTDESTPITCH + 1): + cirrus_hook_read_gr(s, 0x25, &value); + break; + case (CIRRUS_MMIO_BLTSRCPITCH + 0): + cirrus_hook_read_gr(s, 0x26, &value); + break; + case (CIRRUS_MMIO_BLTSRCPITCH + 1): + cirrus_hook_read_gr(s, 0x27, &value); + break; + case (CIRRUS_MMIO_BLTDESTADDR + 0): + cirrus_hook_read_gr(s, 0x28, &value); + break; + case (CIRRUS_MMIO_BLTDESTADDR + 1): + cirrus_hook_read_gr(s, 0x29, &value); + break; + case (CIRRUS_MMIO_BLTDESTADDR + 2): + cirrus_hook_read_gr(s, 0x2a, &value); + break; + case (CIRRUS_MMIO_BLTSRCADDR + 0): + cirrus_hook_read_gr(s, 0x2c, &value); + break; + case (CIRRUS_MMIO_BLTSRCADDR + 1): + cirrus_hook_read_gr(s, 0x2d, &value); + break; + case (CIRRUS_MMIO_BLTSRCADDR + 2): + cirrus_hook_read_gr(s, 0x2e, &value); + break; + case CIRRUS_MMIO_BLTWRITEMASK: + cirrus_hook_read_gr(s, 0x2f, &value); + break; + case CIRRUS_MMIO_BLTMODE: + cirrus_hook_read_gr(s, 0x30, &value); + break; + case CIRRUS_MMIO_BLTROP: + cirrus_hook_read_gr(s, 0x32, &value); + break; + case CIRRUS_MMIO_BLTMODEEXT: + cirrus_hook_read_gr(s, 0x33, &value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0): + cirrus_hook_read_gr(s, 0x34, &value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1): + cirrus_hook_read_gr(s, 0x35, &value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0): + cirrus_hook_read_gr(s, 0x38, &value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1): + cirrus_hook_read_gr(s, 0x39, &value); + break; + case CIRRUS_MMIO_BLTSTATUS: + cirrus_hook_read_gr(s, 0x31, &value); + break; + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: mmio read - address 0x%04x\n", address); +#endif + break; + } + + return (uint8_t) value; +} + +static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address, + uint8_t value) +{ + switch (address) { + case (CIRRUS_MMIO_BLTBGCOLOR + 0): + cirrus_hook_write_gr(s, 0x00, value); + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 1): + cirrus_hook_write_gr(s, 0x10, value); + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 2): + cirrus_hook_write_gr(s, 0x12, value); + break; + case (CIRRUS_MMIO_BLTBGCOLOR + 3): + cirrus_hook_write_gr(s, 0x14, value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 0): + cirrus_hook_write_gr(s, 0x01, value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 1): + cirrus_hook_write_gr(s, 0x11, value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 2): + cirrus_hook_write_gr(s, 0x13, value); + break; + case (CIRRUS_MMIO_BLTFGCOLOR + 3): + cirrus_hook_write_gr(s, 0x15, value); + break; + case (CIRRUS_MMIO_BLTWIDTH + 0): + cirrus_hook_write_gr(s, 0x20, value); + break; + case (CIRRUS_MMIO_BLTWIDTH + 1): + cirrus_hook_write_gr(s, 0x21, value); + break; + case (CIRRUS_MMIO_BLTHEIGHT + 0): + cirrus_hook_write_gr(s, 0x22, value); + break; + case (CIRRUS_MMIO_BLTHEIGHT + 1): + cirrus_hook_write_gr(s, 0x23, value); + break; + case (CIRRUS_MMIO_BLTDESTPITCH + 0): + cirrus_hook_write_gr(s, 0x24, value); + break; + case (CIRRUS_MMIO_BLTDESTPITCH + 1): + cirrus_hook_write_gr(s, 0x25, value); + break; + case (CIRRUS_MMIO_BLTSRCPITCH + 0): + cirrus_hook_write_gr(s, 0x26, value); + break; + case (CIRRUS_MMIO_BLTSRCPITCH + 1): + cirrus_hook_write_gr(s, 0x27, value); + break; + case (CIRRUS_MMIO_BLTDESTADDR + 0): + cirrus_hook_write_gr(s, 0x28, value); + break; + case (CIRRUS_MMIO_BLTDESTADDR + 1): + cirrus_hook_write_gr(s, 0x29, value); + break; + case (CIRRUS_MMIO_BLTDESTADDR + 2): + cirrus_hook_write_gr(s, 0x2a, value); + break; + case (CIRRUS_MMIO_BLTDESTADDR + 3): + /* ignored */ + break; + case (CIRRUS_MMIO_BLTSRCADDR + 0): + cirrus_hook_write_gr(s, 0x2c, value); + break; + case (CIRRUS_MMIO_BLTSRCADDR + 1): + cirrus_hook_write_gr(s, 0x2d, value); + break; + case (CIRRUS_MMIO_BLTSRCADDR + 2): + cirrus_hook_write_gr(s, 0x2e, value); + break; + case CIRRUS_MMIO_BLTWRITEMASK: + cirrus_hook_write_gr(s, 0x2f, value); + break; + case CIRRUS_MMIO_BLTMODE: + cirrus_hook_write_gr(s, 0x30, value); + break; + case CIRRUS_MMIO_BLTROP: + cirrus_hook_write_gr(s, 0x32, value); + break; + case CIRRUS_MMIO_BLTMODEEXT: + cirrus_hook_write_gr(s, 0x33, value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0): + cirrus_hook_write_gr(s, 0x34, value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1): + cirrus_hook_write_gr(s, 0x35, value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0): + cirrus_hook_write_gr(s, 0x38, value); + break; + case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1): + cirrus_hook_write_gr(s, 0x39, value); + break; + case CIRRUS_MMIO_BLTSTATUS: + cirrus_hook_write_gr(s, 0x31, value); + break; + default: +#ifdef DEBUG_CIRRUS + printf("cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n", + address, value); +#endif + break; + } +} + +/*************************************** + * + * write mode 4/5 + * + * assume TARGET_PAGE_SIZE >= 16 + * + ***************************************/ + +static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s, + unsigned mode, + unsigned offset, + uint32_t mem_value) +{ + int x; + unsigned val = mem_value; + uint8_t *dst; + + dst = s->vram_ptr + offset; + for (x = 0; x < 8; x++) { + if (val & 0x80) { + *dst++ = s->cirrus_shadow_gr1; + } else if (mode == 5) { + *dst++ = s->cirrus_shadow_gr0; + } + val <<= 1; + } + cpu_physical_memory_set_dirty(s->vram_offset + offset); + cpu_physical_memory_set_dirty(s->vram_offset + offset + 7); +} + +static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s, + unsigned mode, + unsigned offset, + uint32_t mem_value) +{ + int x; + unsigned val = mem_value; + uint8_t *dst; + + dst = s->vram_ptr + offset; + for (x = 0; x < 8; x++) { + if (val & 0x80) { + *dst++ = s->cirrus_shadow_gr1; + *dst++ = s->gr[0x11]; + } else if (mode == 5) { + *dst++ = s->cirrus_shadow_gr0; + *dst++ = s->gr[0x10]; + } + val <<= 1; + } + cpu_physical_memory_set_dirty(s->vram_offset + offset); + cpu_physical_memory_set_dirty(s->vram_offset + offset + 15); +} + +/*************************************** + * + * memory access between 0xa0000-0xbffff + * + ***************************************/ + +static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr) +{ + CirrusVGAState *s = opaque; + unsigned bank_index; + unsigned bank_offset; + uint32_t val; + + if ((s->sr[0x07] & 0x01) == 0) { + return vga_mem_readb(s, addr); + } + + addr &= 0x1ffff; + + if (addr < 0x10000) { + /* XXX handle bitblt */ + /* video memory */ + bank_index = addr >> 15; + bank_offset = addr & 0x7fff; + if (bank_offset < s->cirrus_bank_limit[bank_index]) { + bank_offset += s->cirrus_bank_base[bank_index]; + if ((s->gr[0x0B] & 0x14) == 0x14) { + bank_offset <<= 4; + } else if (s->gr[0x0B] & 0x02) { + bank_offset <<= 3; + } + bank_offset &= s->cirrus_addr_mask; + val = *(s->vram_ptr + bank_offset); + } else + val = 0xff; + } else if (addr >= 0x18000 && addr < 0x18100) { + /* memory-mapped I/O */ + val = 0xff; + if ((s->sr[0x17] & 0x44) == 0x04) { + val = cirrus_mmio_blt_read(s, addr & 0xff); + } + } else { + val = 0xff; +#ifdef DEBUG_CIRRUS + printf("cirrus: mem_readb %06x\n", addr); +#endif + } + return val; +} + +static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_vga_mem_readb(opaque, addr) << 8; + v |= cirrus_vga_mem_readb(opaque, addr + 1); +#else + v = cirrus_vga_mem_readb(opaque, addr); + v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8; +#endif + return v; +} + +static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_vga_mem_readb(opaque, addr) << 24; + v |= cirrus_vga_mem_readb(opaque, addr + 1) << 16; + v |= cirrus_vga_mem_readb(opaque, addr + 2) << 8; + v |= cirrus_vga_mem_readb(opaque, addr + 3); +#else + v = cirrus_vga_mem_readb(opaque, addr); + v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8; + v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16; + v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24; +#endif + return v; +} + +static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr, + uint32_t mem_value) +{ + CirrusVGAState *s = opaque; + unsigned bank_index; + unsigned bank_offset; + unsigned mode; + + if ((s->sr[0x07] & 0x01) == 0) { + vga_mem_writeb(s, addr, mem_value); + return; + } + + addr &= 0x1ffff; + + if (addr < 0x10000) { + if (s->cirrus_srcptr != s->cirrus_srcptr_end) { + /* bitblt */ + *s->cirrus_srcptr++ = (uint8_t) mem_value; + if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { + cirrus_bitblt_cputovideo_next(s); + } + } else { + /* video memory */ + bank_index = addr >> 15; + bank_offset = addr & 0x7fff; + if (bank_offset < s->cirrus_bank_limit[bank_index]) { + bank_offset += s->cirrus_bank_base[bank_index]; + if ((s->gr[0x0B] & 0x14) == 0x14) { + bank_offset <<= 4; + } else if (s->gr[0x0B] & 0x02) { + bank_offset <<= 3; + } + bank_offset &= s->cirrus_addr_mask; + mode = s->gr[0x05] & 0x7; + if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { + *(s->vram_ptr + bank_offset) = mem_value; + cpu_physical_memory_set_dirty(s->vram_offset + + bank_offset); + } else { + if ((s->gr[0x0B] & 0x14) != 0x14) { + cirrus_mem_writeb_mode4and5_8bpp(s, mode, + bank_offset, + mem_value); + } else { + cirrus_mem_writeb_mode4and5_16bpp(s, mode, + bank_offset, + mem_value); + } + } + } + } + } else if (addr >= 0x18000 && addr < 0x18100) { + /* memory-mapped I/O */ + if ((s->sr[0x17] & 0x44) == 0x04) { + cirrus_mmio_blt_write(s, addr & 0xff, mem_value); + } + } else { +#ifdef DEBUG_CIRRUS + printf("cirrus: mem_writeb %06x value %02x\n", addr, mem_value); +#endif + } +} + +static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_vga_mem_writeb(opaque, addr, (val >> 8) & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 1, val & 0xff); +#else + cirrus_vga_mem_writeb(opaque, addr, val & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff); +#endif +} + +static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_vga_mem_writeb(opaque, addr, (val >> 24) & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 3, val & 0xff); +#else + cirrus_vga_mem_writeb(opaque, addr, val & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff); + cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff); +#endif +} + +static CPUReadMemoryFunc *cirrus_vga_mem_read[3] = { + cirrus_vga_mem_readb, + cirrus_vga_mem_readw, + cirrus_vga_mem_readl, +}; + +static CPUWriteMemoryFunc *cirrus_vga_mem_write[3] = { + cirrus_vga_mem_writeb, + cirrus_vga_mem_writew, + cirrus_vga_mem_writel, +}; + +/*************************************** + * + * hardware cursor + * + ***************************************/ + +static inline void invalidate_cursor1(CirrusVGAState *s) +{ + if (s->last_hw_cursor_size) { + vga_invalidate_scanlines((VGAState *)s, + s->last_hw_cursor_y + s->last_hw_cursor_y_start, + s->last_hw_cursor_y + s->last_hw_cursor_y_end); + } +} + +static inline void cirrus_cursor_compute_yrange(CirrusVGAState *s) +{ + const uint8_t *src; + uint32_t content; + int y, y_min, y_max; + + src = s->vram_ptr + s->real_vram_size - 16 * 1024; + if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) { + src += (s->sr[0x13] & 0x3c) * 256; + y_min = 64; + y_max = -1; + for(y = 0; y < 64; y++) { + content = ((uint32_t *)src)[0] | + ((uint32_t *)src)[1] | + ((uint32_t *)src)[2] | + ((uint32_t *)src)[3]; + if (content) { + if (y < y_min) + y_min = y; + if (y > y_max) + y_max = y; + } + src += 16; + } + } else { + src += (s->sr[0x13] & 0x3f) * 256; + y_min = 32; + y_max = -1; + for(y = 0; y < 32; y++) { + content = ((uint32_t *)src)[0] | + ((uint32_t *)(src + 128))[0]; + if (content) { + if (y < y_min) + y_min = y; + if (y > y_max) + y_max = y; + } + src += 4; + } + } + if (y_min > y_max) { + s->last_hw_cursor_y_start = 0; + s->last_hw_cursor_y_end = 0; + } else { + s->last_hw_cursor_y_start = y_min; + s->last_hw_cursor_y_end = y_max + 1; + } +} + +/* NOTE: we do not currently handle the cursor bitmap change, so we + update the cursor only if it moves. */ +static void cirrus_cursor_invalidate(VGAState *s1) +{ + CirrusVGAState *s = (CirrusVGAState *)s1; + int size; + + if (!s->sr[0x12] & CIRRUS_CURSOR_SHOW) { + size = 0; + } else { + if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) + size = 64; + else + size = 32; + } + /* invalidate last cursor and new cursor if any change */ + if (s->last_hw_cursor_size != size || + s->last_hw_cursor_x != s->hw_cursor_x || + s->last_hw_cursor_y != s->hw_cursor_y) { + + invalidate_cursor1(s); + + s->last_hw_cursor_size = size; + s->last_hw_cursor_x = s->hw_cursor_x; + s->last_hw_cursor_y = s->hw_cursor_y; + /* compute the real cursor min and max y */ + cirrus_cursor_compute_yrange(s); + invalidate_cursor1(s); + } +} + +static void cirrus_cursor_draw_line(VGAState *s1, uint8_t *d1, int scr_y) +{ + CirrusVGAState *s = (CirrusVGAState *)s1; + int w, h, bpp, x1, x2, poffset; + unsigned int color0, color1; + const uint8_t *palette, *src; + uint32_t content; + + if (!(s->sr[0x12] & CIRRUS_CURSOR_SHOW)) + return; + /* fast test to see if the cursor intersects with the scan line */ + if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) { + h = 64; + } else { + h = 32; + } + if (scr_y < s->hw_cursor_y || + scr_y >= (s->hw_cursor_y + h)) + return; + + src = s->vram_ptr + s->real_vram_size - 16 * 1024; + if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) { + src += (s->sr[0x13] & 0x3c) * 256; + src += (scr_y - s->hw_cursor_y) * 16; + poffset = 8; + content = ((uint32_t *)src)[0] | + ((uint32_t *)src)[1] | + ((uint32_t *)src)[2] | + ((uint32_t *)src)[3]; + } else { + src += (s->sr[0x13] & 0x3f) * 256; + src += (scr_y - s->hw_cursor_y) * 4; + poffset = 128; + content = ((uint32_t *)src)[0] | + ((uint32_t *)(src + 128))[0]; + } + /* if nothing to draw, no need to continue */ + if (!content) + return; + w = h; + + x1 = s->hw_cursor_x; + if (x1 >= s->last_scr_width) + return; + x2 = s->hw_cursor_x + w; + if (x2 > s->last_scr_width) + x2 = s->last_scr_width; + w = x2 - x1; + palette = s->cirrus_hidden_palette; + color0 = s->rgb_to_pixel(c6_to_8(palette[0x0 * 3]), + c6_to_8(palette[0x0 * 3 + 1]), + c6_to_8(palette[0x0 * 3 + 2])); + color1 = s->rgb_to_pixel(c6_to_8(palette[0xf * 3]), + c6_to_8(palette[0xf * 3 + 1]), + c6_to_8(palette[0xf * 3 + 2])); + bpp = ((s->ds->depth + 7) >> 3); + d1 += x1 * bpp; + switch(s->ds->depth) { + default: + break; + case 8: + vga_draw_cursor_line_8(d1, src, poffset, w, color0, color1, 0xff); + break; + case 15: + vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0x7fff); + break; + case 16: + vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0xffff); + break; + case 32: + vga_draw_cursor_line_32(d1, src, poffset, w, color0, color1, 0xffffff); + break; + } +} + +/*************************************** + * + * LFB memory access + * + ***************************************/ + +static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + uint32_t ret; + + addr &= s->cirrus_addr_mask; + + if (((s->sr[0x17] & 0x44) == 0x44) && + ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) { + /* memory-mapped I/O */ + ret = cirrus_mmio_blt_read(s, addr & 0xff); + } else if (0) { + /* XXX handle bitblt */ + ret = 0xff; + } else { + /* video memory */ + if ((s->gr[0x0B] & 0x14) == 0x14) { + addr <<= 4; + } else if (s->gr[0x0B] & 0x02) { + addr <<= 3; + } + addr &= s->cirrus_addr_mask; + ret = *(s->vram_ptr + addr); + } + + return ret; +} + +static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_linear_readb(opaque, addr) << 8; + v |= cirrus_linear_readb(opaque, addr + 1); +#else + v = cirrus_linear_readb(opaque, addr); + v |= cirrus_linear_readb(opaque, addr + 1) << 8; +#endif + return v; +} + +static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_linear_readb(opaque, addr) << 24; + v |= cirrus_linear_readb(opaque, addr + 1) << 16; + v |= cirrus_linear_readb(opaque, addr + 2) << 8; + v |= cirrus_linear_readb(opaque, addr + 3); +#else + v = cirrus_linear_readb(opaque, addr); + v |= cirrus_linear_readb(opaque, addr + 1) << 8; + v |= cirrus_linear_readb(opaque, addr + 2) << 16; + v |= cirrus_linear_readb(opaque, addr + 3) << 24; +#endif + return v; +} + +static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + unsigned mode; + + addr &= s->cirrus_addr_mask; + + if (((s->sr[0x17] & 0x44) == 0x44) && + ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) { + /* memory-mapped I/O */ + cirrus_mmio_blt_write(s, addr & 0xff, val); + } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { + /* bitblt */ + *s->cirrus_srcptr++ = (uint8_t) val; + if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { + cirrus_bitblt_cputovideo_next(s); + } + } else { + /* video memory */ + if ((s->gr[0x0B] & 0x14) == 0x14) { + addr <<= 4; + } else if (s->gr[0x0B] & 0x02) { + addr <<= 3; + } + addr &= s->cirrus_addr_mask; + + mode = s->gr[0x05] & 0x7; + if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { + *(s->vram_ptr + addr) = (uint8_t) val; + cpu_physical_memory_set_dirty(s->vram_offset + addr); + } else { + if ((s->gr[0x0B] & 0x14) != 0x14) { + cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val); + } else { + cirrus_mem_writeb_mode4and5_16bpp(s, mode, addr, val); + } + } + } +} + +static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_linear_writeb(opaque, addr, (val >> 8) & 0xff); + cirrus_linear_writeb(opaque, addr + 1, val & 0xff); +#else + cirrus_linear_writeb(opaque, addr, val & 0xff); + cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff); +#endif +} + +static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_linear_writeb(opaque, addr, (val >> 24) & 0xff); + cirrus_linear_writeb(opaque, addr + 1, (val >> 16) & 0xff); + cirrus_linear_writeb(opaque, addr + 2, (val >> 8) & 0xff); + cirrus_linear_writeb(opaque, addr + 3, val & 0xff); +#else + cirrus_linear_writeb(opaque, addr, val & 0xff); + cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff); + cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff); + cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff); +#endif +} + + +static CPUReadMemoryFunc *cirrus_linear_read[3] = { + cirrus_linear_readb, + cirrus_linear_readw, + cirrus_linear_readl, +}; + +static CPUWriteMemoryFunc *cirrus_linear_write[3] = { + cirrus_linear_writeb, + cirrus_linear_writew, + cirrus_linear_writel, +}; + +static void cirrus_linear_mem_writeb(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= s->cirrus_addr_mask; + *(s->vram_ptr + addr) = val; + cpu_physical_memory_set_dirty(s->vram_offset + addr); +} + +static void cirrus_linear_mem_writew(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= s->cirrus_addr_mask; + cpu_to_le16w((uint16_t *)(s->vram_ptr + addr), val); + cpu_physical_memory_set_dirty(s->vram_offset + addr); +} + +static void cirrus_linear_mem_writel(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= s->cirrus_addr_mask; + cpu_to_le32w((uint32_t *)(s->vram_ptr + addr), val); + cpu_physical_memory_set_dirty(s->vram_offset + addr); +} + +/*************************************** + * + * system to screen memory access + * + ***************************************/ + + +static uint32_t cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr) +{ + uint32_t ret; + + /* XXX handle bitblt */ + ret = 0xff; + return ret; +} + +static uint32_t cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_linear_bitblt_readb(opaque, addr) << 8; + v |= cirrus_linear_bitblt_readb(opaque, addr + 1); +#else + v = cirrus_linear_bitblt_readb(opaque, addr); + v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8; +#endif + return v; +} + +static uint32_t cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_linear_bitblt_readb(opaque, addr) << 24; + v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 16; + v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 8; + v |= cirrus_linear_bitblt_readb(opaque, addr + 3); +#else + v = cirrus_linear_bitblt_readb(opaque, addr); + v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8; + v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16; + v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24; +#endif + return v; +} + +static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + if (s->cirrus_srcptr != s->cirrus_srcptr_end) { + /* bitblt */ + *s->cirrus_srcptr++ = (uint8_t) val; + if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { + cirrus_bitblt_cputovideo_next(s); + } + } +} + +static void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_linear_bitblt_writeb(opaque, addr, (val >> 8) & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 1, val & 0xff); +#else + cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff); +#endif +} + +static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_linear_bitblt_writeb(opaque, addr, (val >> 24) & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 16) & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 8) & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 3, val & 0xff); +#else + cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff); + cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff); +#endif +} + + +static CPUReadMemoryFunc *cirrus_linear_bitblt_read[3] = { + cirrus_linear_bitblt_readb, + cirrus_linear_bitblt_readw, + cirrus_linear_bitblt_readl, +}; + +static CPUWriteMemoryFunc *cirrus_linear_bitblt_write[3] = { + cirrus_linear_bitblt_writeb, + cirrus_linear_bitblt_writew, + cirrus_linear_bitblt_writel, +}; + +/* Compute the memory access functions */ +static void cirrus_update_memory_access(CirrusVGAState *s) +{ + unsigned mode; + + if ((s->sr[0x17] & 0x44) == 0x44) { + goto generic_io; + } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { + goto generic_io; + } else { + if ((s->gr[0x0B] & 0x14) == 0x14) { + goto generic_io; + } else if (s->gr[0x0B] & 0x02) { + goto generic_io; + } + + mode = s->gr[0x05] & 0x7; + if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) { + s->cirrus_linear_write[0] = cirrus_linear_mem_writeb; + s->cirrus_linear_write[1] = cirrus_linear_mem_writew; + s->cirrus_linear_write[2] = cirrus_linear_mem_writel; + } else { + generic_io: + s->cirrus_linear_write[0] = cirrus_linear_writeb; + s->cirrus_linear_write[1] = cirrus_linear_writew; + s->cirrus_linear_write[2] = cirrus_linear_writel; + } + } +} + + +/* I/O ports */ + +static uint32_t vga_ioport_read(void *opaque, uint32_t addr) +{ + CirrusVGAState *s = opaque; + int val, index; + + /* check port range access depending on color/monochrome mode */ + if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) + || (addr >= 0x3d0 && addr <= 0x3df + && !(s->msr & MSR_COLOR_EMULATION))) { + val = 0xff; + } else { + switch (addr) { + case 0x3c0: + if (s->ar_flip_flop == 0) { + val = s->ar_index; + } else { + val = 0; + } + break; + case 0x3c1: + index = s->ar_index & 0x1f; + if (index < 21) + val = s->ar[index]; + else + val = 0; + break; + case 0x3c2: + val = s->st00; + break; + case 0x3c4: + val = s->sr_index; + break; + case 0x3c5: + if (cirrus_hook_read_sr(s, s->sr_index, &val)) + break; + val = s->sr[s->sr_index]; +#ifdef DEBUG_VGA_REG + printf("vga: read SR%x = 0x%02x\n", s->sr_index, val); +#endif + break; + case 0x3c6: + cirrus_read_hidden_dac(s, &val); + break; + case 0x3c7: + val = s->dac_state; + break; + case 0x3c8: + val = s->dac_write_index; + s->cirrus_hidden_dac_lockindex = 0; + break; + case 0x3c9: + if (cirrus_hook_read_palette(s, &val)) + break; + val = s->palette[s->dac_read_index * 3 + s->dac_sub_index]; + if (++s->dac_sub_index == 3) { + s->dac_sub_index = 0; + s->dac_read_index++; + } + break; + case 0x3ca: + val = s->fcr; + break; + case 0x3cc: + val = s->msr; + break; + case 0x3ce: + val = s->gr_index; + break; + case 0x3cf: + if (cirrus_hook_read_gr(s, s->gr_index, &val)) + break; + val = s->gr[s->gr_index]; +#ifdef DEBUG_VGA_REG + printf("vga: read GR%x = 0x%02x\n", s->gr_index, val); +#endif + break; + case 0x3b4: + case 0x3d4: + val = s->cr_index; + break; + case 0x3b5: + case 0x3d5: + if (cirrus_hook_read_cr(s, s->cr_index, &val)) + break; + val = s->cr[s->cr_index]; +#ifdef DEBUG_VGA_REG + printf("vga: read CR%x = 0x%02x\n", s->cr_index, val); +#endif + break; + case 0x3ba: + case 0x3da: + /* just toggle to fool polling */ + s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE; + val = s->st01; + s->ar_flip_flop = 0; + break; + default: + val = 0x00; + break; + } + } +#if defined(DEBUG_VGA) + printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val); +#endif + return val; +} + +static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ + CirrusVGAState *s = opaque; + int index; + + /* check port range access depending on color/monochrome mode */ + if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) + || (addr >= 0x3d0 && addr <= 0x3df + && !(s->msr & MSR_COLOR_EMULATION))) + return; + +#ifdef DEBUG_VGA + printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val); +#endif + + switch (addr) { + case 0x3c0: + if (s->ar_flip_flop == 0) { + val &= 0x3f; + s->ar_index = val; + } else { + index = s->ar_index & 0x1f; + switch (index) { + case 0x00 ... 0x0f: + s->ar[index] = val & 0x3f; + break; + case 0x10: + s->ar[index] = val & ~0x10; + break; + case 0x11: + s->ar[index] = val; + break; + case 0x12: + s->ar[index] = val & ~0xc0; + break; + case 0x13: + s->ar[index] = val & ~0xf0; + break; + case 0x14: + s->ar[index] = val & ~0xf0; + break; + default: + break; + } + } + s->ar_flip_flop ^= 1; + break; + case 0x3c2: + s->msr = val & ~0x10; + break; + case 0x3c4: + s->sr_index = val; + break; + case 0x3c5: + if (cirrus_hook_write_sr(s, s->sr_index, val)) + break; +#ifdef DEBUG_VGA_REG + printf("vga: write SR%x = 0x%02x\n", s->sr_index, val); +#endif + s->sr[s->sr_index] = val & sr_mask[s->sr_index]; + break; + case 0x3c6: + cirrus_write_hidden_dac(s, val); + break; + case 0x3c7: + s->dac_read_index = val; + s->dac_sub_index = 0; + s->dac_state = 3; + break; + case 0x3c8: + s->dac_write_index = val; + s->dac_sub_index = 0; + s->dac_state = 0; + break; + case 0x3c9: + if (cirrus_hook_write_palette(s, val)) + break; + s->dac_cache[s->dac_sub_index] = val; + if (++s->dac_sub_index == 3) { + memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3); + s->dac_sub_index = 0; + s->dac_write_index++; + } + break; + case 0x3ce: + s->gr_index = val; + break; + case 0x3cf: + if (cirrus_hook_write_gr(s, s->gr_index, val)) + break; +#ifdef DEBUG_VGA_REG + printf("vga: write GR%x = 0x%02x\n", s->gr_index, val); +#endif + s->gr[s->gr_index] = val & gr_mask[s->gr_index]; + break; + case 0x3b4: + case 0x3d4: + s->cr_index = val; + break; + case 0x3b5: + case 0x3d5: + if (cirrus_hook_write_cr(s, s->cr_index, val)) + break; +#ifdef DEBUG_VGA_REG + printf("vga: write CR%x = 0x%02x\n", s->cr_index, val); +#endif + /* handle CR0-7 protection */ + if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) { + /* can always write bit 4 of CR7 */ + if (s->cr_index == 7) + s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10); + return; + } + switch (s->cr_index) { + case 0x01: /* horizontal display end */ + case 0x07: + case 0x09: + case 0x0c: + case 0x0d: + case 0x12: /* veritcal display end */ + s->cr[s->cr_index] = val; + break; + + default: + s->cr[s->cr_index] = val; + break; + } + break; + case 0x3ba: + case 0x3da: + s->fcr = val & 0x10; + break; + } +} + +/*************************************** + * + * memory-mapped I/O access + * + ***************************************/ + +static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= CIRRUS_PNPMMIO_SIZE - 1; + + if (addr >= 0x100) { + return cirrus_mmio_blt_read(s, addr - 0x100); + } else { + return vga_ioport_read(s, addr + 0x3c0); + } +} + +static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_mmio_readb(opaque, addr) << 8; + v |= cirrus_mmio_readb(opaque, addr + 1); +#else + v = cirrus_mmio_readb(opaque, addr); + v |= cirrus_mmio_readb(opaque, addr + 1) << 8; +#endif + return v; +} + +static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; +#ifdef TARGET_WORDS_BIGENDIAN + v = cirrus_mmio_readb(opaque, addr) << 24; + v |= cirrus_mmio_readb(opaque, addr + 1) << 16; + v |= cirrus_mmio_readb(opaque, addr + 2) << 8; + v |= cirrus_mmio_readb(opaque, addr + 3); +#else + v = cirrus_mmio_readb(opaque, addr); + v |= cirrus_mmio_readb(opaque, addr + 1) << 8; + v |= cirrus_mmio_readb(opaque, addr + 2) << 16; + v |= cirrus_mmio_readb(opaque, addr + 3) << 24; +#endif + return v; +} + +static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + CirrusVGAState *s = (CirrusVGAState *) opaque; + + addr &= CIRRUS_PNPMMIO_SIZE - 1; + + if (addr >= 0x100) { + cirrus_mmio_blt_write(s, addr - 0x100, val); + } else { + vga_ioport_write(s, addr + 0x3c0, val); + } +} + +static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_mmio_writeb(opaque, addr, (val >> 8) & 0xff); + cirrus_mmio_writeb(opaque, addr + 1, val & 0xff); +#else + cirrus_mmio_writeb(opaque, addr, val & 0xff); + cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff); +#endif +} + +static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr, + uint32_t val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + cirrus_mmio_writeb(opaque, addr, (val >> 24) & 0xff); + cirrus_mmio_writeb(opaque, addr + 1, (val >> 16) & 0xff); + cirrus_mmio_writeb(opaque, addr + 2, (val >> 8) & 0xff); + cirrus_mmio_writeb(opaque, addr + 3, val & 0xff); +#else + cirrus_mmio_writeb(opaque, addr, val & 0xff); + cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff); + cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff); + cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff); +#endif +} + + +static CPUReadMemoryFunc *cirrus_mmio_read[3] = { + cirrus_mmio_readb, + cirrus_mmio_readw, + cirrus_mmio_readl, +}; + +static CPUWriteMemoryFunc *cirrus_mmio_write[3] = { + cirrus_mmio_writeb, + cirrus_mmio_writew, + cirrus_mmio_writel, +}; + +/* load/save state */ + +static void cirrus_vga_save(QEMUFile *f, void *opaque) +{ + CirrusVGAState *s = opaque; + + qemu_put_be32s(f, &s->latch); + qemu_put_8s(f, &s->sr_index); + qemu_put_buffer(f, s->sr, 256); + qemu_put_8s(f, &s->gr_index); + qemu_put_8s(f, &s->cirrus_shadow_gr0); + qemu_put_8s(f, &s->cirrus_shadow_gr1); + qemu_put_buffer(f, s->gr + 2, 254); + qemu_put_8s(f, &s->ar_index); + qemu_put_buffer(f, s->ar, 21); + qemu_put_be32s(f, &s->ar_flip_flop); + qemu_put_8s(f, &s->cr_index); + qemu_put_buffer(f, s->cr, 256); + qemu_put_8s(f, &s->msr); + qemu_put_8s(f, &s->fcr); + qemu_put_8s(f, &s->st00); + qemu_put_8s(f, &s->st01); + + qemu_put_8s(f, &s->dac_state); + qemu_put_8s(f, &s->dac_sub_index); + qemu_put_8s(f, &s->dac_read_index); + qemu_put_8s(f, &s->dac_write_index); + qemu_put_buffer(f, s->dac_cache, 3); + qemu_put_buffer(f, s->palette, 768); + + qemu_put_be32s(f, &s->bank_offset); + + qemu_put_8s(f, &s->cirrus_hidden_dac_lockindex); + qemu_put_8s(f, &s->cirrus_hidden_dac_data); + + qemu_put_be32s(f, &s->hw_cursor_x); + qemu_put_be32s(f, &s->hw_cursor_y); + /* XXX: we do not save the bitblt state - we assume we do not save + the state when the blitter is active */ +} + +static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id) +{ + CirrusVGAState *s = opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_be32s(f, &s->latch); + qemu_get_8s(f, &s->sr_index); + qemu_get_buffer(f, s->sr, 256); + qemu_get_8s(f, &s->gr_index); + qemu_get_8s(f, &s->cirrus_shadow_gr0); + qemu_get_8s(f, &s->cirrus_shadow_gr1); + s->gr[0x00] = s->cirrus_shadow_gr0 & 0x0f; + s->gr[0x01] = s->cirrus_shadow_gr1 & 0x0f; + qemu_get_buffer(f, s->gr + 2, 254); + qemu_get_8s(f, &s->ar_index); + qemu_get_buffer(f, s->ar, 21); + qemu_get_be32s(f, &s->ar_flip_flop); + qemu_get_8s(f, &s->cr_index); + qemu_get_buffer(f, s->cr, 256); + qemu_get_8s(f, &s->msr); + qemu_get_8s(f, &s->fcr); + qemu_get_8s(f, &s->st00); + qemu_get_8s(f, &s->st01); + + qemu_get_8s(f, &s->dac_state); + qemu_get_8s(f, &s->dac_sub_index); + qemu_get_8s(f, &s->dac_read_index); + qemu_get_8s(f, &s->dac_write_index); + qemu_get_buffer(f, s->dac_cache, 3); + qemu_get_buffer(f, s->palette, 768); + + qemu_get_be32s(f, &s->bank_offset); + + qemu_get_8s(f, &s->cirrus_hidden_dac_lockindex); + qemu_get_8s(f, &s->cirrus_hidden_dac_data); + + qemu_get_be32s(f, &s->hw_cursor_x); + qemu_get_be32s(f, &s->hw_cursor_y); + + /* force refresh */ + s->graphic_mode = -1; + cirrus_update_bank_ptr(s, 0); + cirrus_update_bank_ptr(s, 1); + return 0; +} + +/*************************************** + * + * initialize + * + ***************************************/ + +static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci) +{ + int vga_io_memory, i; + static int inited; + + if (!inited) { + inited = 1; + for(i = 0;i < 256; i++) + rop_to_index[i] = CIRRUS_ROP_NOP_INDEX; /* nop rop */ + rop_to_index[CIRRUS_ROP_0] = 0; + rop_to_index[CIRRUS_ROP_SRC_AND_DST] = 1; + rop_to_index[CIRRUS_ROP_NOP] = 2; + rop_to_index[CIRRUS_ROP_SRC_AND_NOTDST] = 3; + rop_to_index[CIRRUS_ROP_NOTDST] = 4; + rop_to_index[CIRRUS_ROP_SRC] = 5; + rop_to_index[CIRRUS_ROP_1] = 6; + rop_to_index[CIRRUS_ROP_NOTSRC_AND_DST] = 7; + rop_to_index[CIRRUS_ROP_SRC_XOR_DST] = 8; + rop_to_index[CIRRUS_ROP_SRC_OR_DST] = 9; + rop_to_index[CIRRUS_ROP_NOTSRC_OR_NOTDST] = 10; + rop_to_index[CIRRUS_ROP_SRC_NOTXOR_DST] = 11; + rop_to_index[CIRRUS_ROP_SRC_OR_NOTDST] = 12; + rop_to_index[CIRRUS_ROP_NOTSRC] = 13; + rop_to_index[CIRRUS_ROP_NOTSRC_OR_DST] = 14; + rop_to_index[CIRRUS_ROP_NOTSRC_AND_NOTDST] = 15; + } + + register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s); + + register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s); + register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s); + register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s); + register_ioport_write(0x3da, 1, 1, vga_ioport_write, s); + + register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s); + + register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s); + register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s); + register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s); + register_ioport_read(0x3da, 1, 1, vga_ioport_read, s); + + vga_io_memory = cpu_register_io_memory(0, cirrus_vga_mem_read, + cirrus_vga_mem_write, s); + cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, + vga_io_memory); + + s->sr[0x06] = 0x0f; + if (device_id == CIRRUS_ID_CLGD5446) { + /* 4MB 64 bit memory config, always PCI */ + s->sr[0x1F] = 0x2d; // MemClock + s->gr[0x18] = 0x0f; // fastest memory configuration +#if 1 + s->sr[0x0f] = 0x98; + s->sr[0x17] = 0x20; + s->sr[0x15] = 0x04; /* memory size, 3=2MB, 4=4MB */ + s->real_vram_size = 4096 * 1024; +#else + s->sr[0x0f] = 0x18; + s->sr[0x17] = 0x20; + s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */ + s->real_vram_size = 2048 * 1024; +#endif + } else { + s->sr[0x1F] = 0x22; // MemClock + s->sr[0x0F] = CIRRUS_MEMSIZE_2M; + if (is_pci) + s->sr[0x17] = CIRRUS_BUSTYPE_PCI; + else + s->sr[0x17] = CIRRUS_BUSTYPE_ISA; + s->real_vram_size = 2048 * 1024; + s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */ + } + s->cr[0x27] = device_id; + + /* Win2K seems to assume that the pattern buffer is at 0xff + initially ! */ + memset(s->vram_ptr, 0xff, s->real_vram_size); + + s->cirrus_hidden_dac_lockindex = 5; + s->cirrus_hidden_dac_data = 0; + + /* I/O handler for LFB */ + s->cirrus_linear_io_addr = + cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write, + s); + s->cirrus_linear_write = cpu_get_io_memory_write(s->cirrus_linear_io_addr); + + /* I/O handler for LFB */ + s->cirrus_linear_bitblt_io_addr = + cpu_register_io_memory(0, cirrus_linear_bitblt_read, cirrus_linear_bitblt_write, + s); + + /* I/O handler for memory-mapped I/O */ + s->cirrus_mmio_io_addr = + cpu_register_io_memory(0, cirrus_mmio_read, cirrus_mmio_write, s); + + /* XXX: s->vram_size must be a power of two */ + s->cirrus_addr_mask = s->real_vram_size - 1; + s->linear_mmio_mask = s->real_vram_size - 256; + + s->get_bpp = cirrus_get_bpp; + s->get_offsets = cirrus_get_offsets; + s->get_resolution = cirrus_get_resolution; + s->cursor_invalidate = cirrus_cursor_invalidate; + s->cursor_draw_line = cirrus_cursor_draw_line; + + register_savevm("cirrus_vga", 0, 1, cirrus_vga_save, cirrus_vga_load, s); +} + +/*************************************** + * + * ISA bus support + * + ***************************************/ + +void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base, + unsigned long vga_ram_offset, int vga_ram_size) +{ + CirrusVGAState *s; + + s = qemu_mallocz(sizeof(CirrusVGAState)); + + vga_common_init((VGAState *)s, + ds, vga_ram_base, vga_ram_offset, vga_ram_size); + cirrus_init_common(s, CIRRUS_ID_CLGD5430, 0); + /* XXX ISA-LFB support */ +} + +/*************************************** + * + * PCI bus support + * + ***************************************/ + +static void cirrus_pci_lfb_map(PCIDevice *d, int region_num, + uint32_t addr, uint32_t size, int type) +{ + CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga; + + /* XXX: add byte swapping apertures */ + cpu_register_physical_memory(addr, s->vram_size, + s->cirrus_linear_io_addr); + cpu_register_physical_memory(addr + 0x1000000, 0x400000, + s->cirrus_linear_bitblt_io_addr); +} + +static void cirrus_pci_mmio_map(PCIDevice *d, int region_num, + uint32_t addr, uint32_t size, int type) +{ + CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga; + + cpu_register_physical_memory(addr, CIRRUS_PNPMMIO_SIZE, + s->cirrus_mmio_io_addr); +} + +void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, + unsigned long vga_ram_offset, int vga_ram_size) +{ + PCICirrusVGAState *d; + uint8_t *pci_conf; + CirrusVGAState *s; + int device_id; + + device_id = CIRRUS_ID_CLGD5446; + + /* setup PCI configuration registers */ + d = (PCICirrusVGAState *)pci_register_device(bus, "Cirrus VGA", + sizeof(PCICirrusVGAState), + -1, NULL, NULL); + pci_conf = d->dev.config; + pci_conf[0x00] = (uint8_t) (PCI_VENDOR_CIRRUS & 0xff); + pci_conf[0x01] = (uint8_t) (PCI_VENDOR_CIRRUS >> 8); + pci_conf[0x02] = (uint8_t) (device_id & 0xff); + pci_conf[0x03] = (uint8_t) (device_id >> 8); + pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS; + pci_conf[0x0a] = PCI_CLASS_SUB_VGA; + pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY; + pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h; + + /* setup VGA */ + s = &d->cirrus_vga; + vga_common_init((VGAState *)s, + ds, vga_ram_base, vga_ram_offset, vga_ram_size); + cirrus_init_common(s, device_id, 1); + + /* setup memory space */ + /* memory #0 LFB */ + /* memory #1 memory-mapped I/O */ + /* XXX: s->vram_size must be a power of two */ + pci_register_io_region((PCIDevice *)d, 0, 0x2000000, + PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map); + if (device_id == CIRRUS_ID_CLGD5446) { + pci_register_io_region((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE, + PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map); + } + /* XXX: ROM BIOS */ +} diff --git a/tools/ioemu/hw/cirrus_vga_rop.h b/tools/ioemu/hw/cirrus_vga_rop.h new file mode 100644 index 0000000000..c54f1258b3 --- /dev/null +++ b/tools/ioemu/hw/cirrus_vga_rop.h @@ -0,0 +1,78 @@ +/* + * QEMU Cirrus CLGD 54xx VGA Emulator. + * + * Copyright (c) 2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +static void +glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + dstpitch -= bltwidth; + srcpitch -= bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { + ROP_OP(*dst, *src); + dst++; + src++; + } + dst += dstpitch; + src += srcpitch; + } +} + +static void +glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s, + uint8_t *dst,const uint8_t *src, + int dstpitch,int srcpitch, + int bltwidth,int bltheight) +{ + int x,y; + dstpitch += bltwidth; + srcpitch += bltwidth; + for (y = 0; y < bltheight; y++) { + for (x = 0; x < bltwidth; x++) { + ROP_OP(*dst, *src); + dst--; + src--; + } + dst += dstpitch; + src += srcpitch; + } +} + +#define DEPTH 8 +#include "cirrus_vga_rop2.h" + +#define DEPTH 16 +#include "cirrus_vga_rop2.h" + +#define DEPTH 24 +#include "cirrus_vga_rop2.h" + +#define DEPTH 32 +#include "cirrus_vga_rop2.h" + +#undef ROP_NAME +#undef ROP_OP diff --git a/tools/ioemu/hw/cirrus_vga_rop2.h b/tools/ioemu/hw/cirrus_vga_rop2.h new file mode 100644 index 0000000000..5521870c8b --- /dev/null +++ b/tools/ioemu/hw/cirrus_vga_rop2.h @@ -0,0 +1,260 @@ +/* + * QEMU Cirrus CLGD 54xx VGA Emulator. + * + * Copyright (c) 2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if DEPTH == 8 +#define PUTPIXEL() ROP_OP(d[0], col) +#elif DEPTH == 16 +#define PUTPIXEL() ROP_OP(((uint16_t *)d)[0], col); +#elif DEPTH == 24 +#define PUTPIXEL() ROP_OP(d[0], col); \ + ROP_OP(d[1], (col >> 8)); \ + ROP_OP(d[2], (col >> 16)) +#elif DEPTH == 32 +#define PUTPIXEL() ROP_OP(((uint32_t *)d)[0], col) +#else +#error unsupported DEPTH +#endif + +static void +glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH) + (CirrusVGAState * s, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint8_t *d; + int x, y, pattern_y, pattern_pitch, pattern_x; + unsigned int col; + const uint8_t *src1; + +#if DEPTH == 8 + pattern_pitch = 8; +#elif DEPTH == 16 + pattern_pitch = 16; +#else + pattern_pitch = 32; +#endif + pattern_y = s->cirrus_blt_srcaddr & 7; + pattern_x = 0; + for(y = 0; y < bltheight; y++) { + d = dst; + src1 = src + pattern_y * pattern_pitch; + for (x = 0; x < bltwidth; x += (DEPTH / 8)) { +#if DEPTH == 8 + col = src1[pattern_x]; + pattern_x = (pattern_x + 1) & 7; +#elif DEPTH == 16 + col = ((uint16_t *)(src1 + pattern_x))[0]; + pattern_x = (pattern_x + 2) & 15; +#elif DEPTH == 24 + { + const uint8_t *src2 = src1 + pattern_x * 3; + col = src2[0] | (src2[1] << 8) | (src2[2] << 16); + pattern_x = (pattern_x + 1) & 7; + } +#else + col = ((uint32_t *)(src1 + pattern_x))[0]; + pattern_x = (pattern_x + 4) & 31; +#endif + PUTPIXEL(); + d += (DEPTH / 8); + } + pattern_y = (pattern_y + 1) & 7; + dst += dstpitch; + } +} + +/* NOTE: srcpitch is ignored */ +static void +glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) + (CirrusVGAState * s, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint8_t *d; + int x, y; + unsigned bits, bits_xor; + unsigned int col; + unsigned bitmask; + unsigned index; + int srcskipleft = 0; + + if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { + bits_xor = 0xff; + col = s->cirrus_blt_bgcol; + } else { + bits_xor = 0x00; + col = s->cirrus_blt_fgcol; + } + + for(y = 0; y < bltheight; y++) { + bitmask = 0x80 >> srcskipleft; + bits = *src++ ^ bits_xor; + d = dst; + for (x = 0; x < bltwidth; x += (DEPTH / 8)) { + if ((bitmask & 0xff) == 0) { + bitmask = 0x80; + bits = *src++ ^ bits_xor; + } + index = (bits & bitmask); + if (index) { + PUTPIXEL(); + } + d += (DEPTH / 8); + bitmask >>= 1; + } + dst += dstpitch; + } +} + +static void +glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) + (CirrusVGAState * s, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint32_t colors[2]; + uint8_t *d; + int x, y; + unsigned bits; + unsigned int col; + unsigned bitmask; + int srcskipleft = 0; + + colors[0] = s->cirrus_blt_bgcol; + colors[1] = s->cirrus_blt_fgcol; + for(y = 0; y < bltheight; y++) { + bitmask = 0x80 >> srcskipleft; + bits = *src++; + d = dst; + for (x = 0; x < bltwidth; x += (DEPTH / 8)) { + if ((bitmask & 0xff) == 0) { + bitmask = 0x80; + bits = *src++; + } + col = colors[!!(bits & bitmask)]; + PUTPIXEL(); + d += (DEPTH / 8); + bitmask >>= 1; + } + dst += dstpitch; + } +} + +static void +glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH) + (CirrusVGAState * s, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint8_t *d; + int x, y, bitpos, pattern_y; + unsigned int bits, bits_xor; + unsigned int col; + + if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { + bits_xor = 0xff; + col = s->cirrus_blt_bgcol; + } else { + bits_xor = 0x00; + col = s->cirrus_blt_fgcol; + } + pattern_y = s->cirrus_blt_srcaddr & 7; + + for(y = 0; y < bltheight; y++) { + bits = src[pattern_y] ^ bits_xor; + bitpos = 7; + d = dst; + for (x = 0; x < bltwidth; x += (DEPTH / 8)) { + if ((bits >> bitpos) & 1) { + PUTPIXEL(); + } + d += (DEPTH / 8); + bitpos = (bitpos - 1) & 7; + } + pattern_y = (pattern_y + 1) & 7; + dst += dstpitch; + } +} + +static void +glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH) + (CirrusVGAState * s, uint8_t * dst, + const uint8_t * src, + int dstpitch, int srcpitch, + int bltwidth, int bltheight) +{ + uint32_t colors[2]; + uint8_t *d; + int x, y, bitpos, pattern_y; + unsigned int bits; + unsigned int col; + + colors[0] = s->cirrus_blt_bgcol; + colors[1] = s->cirrus_blt_fgcol; + pattern_y = s->cirrus_blt_srcaddr & 7; + + for(y = 0; y < bltheight; y++) { + bits = src[pattern_y]; + bitpos = 7; + d = dst; + for (x = 0; x < bltwidth; x += (DEPTH / 8)) { + col = colors[(bits >> bitpos) & 1]; + PUTPIXEL(); + d += (DEPTH / 8); + bitpos = (bitpos - 1) & 7; + } + pattern_y = (pattern_y + 1) & 7; + dst += dstpitch; + } +} + +static void +glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) + (CirrusVGAState *s, + uint8_t *dst, int dst_pitch, + int width, int height) +{ + uint8_t *d, *d1; + uint32_t col; + int x, y; + + col = s->cirrus_blt_fgcol; + + d1 = dst; + for(y = 0; y < height; y++) { + d = d1; + for(x = 0; x < width; x += (DEPTH / 8)) { + PUTPIXEL(); + d += (DEPTH / 8); + } + d1 += dst_pitch; + } +} + +#undef DEPTH +#undef PUTPIXEL diff --git a/tools/ioemu/hw/cuda.c b/tools/ioemu/hw/cuda.c new file mode 100644 index 0000000000..c05cdeb5fe --- /dev/null +++ b/tools/ioemu/hw/cuda.c @@ -0,0 +1,614 @@ +/* + * QEMU CUDA support + * + * Copyright (c) 2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +//#define DEBUG_CUDA +//#define DEBUG_CUDA_PACKET + +/* Bits in B data register: all active low */ +#define TREQ 0x08 /* Transfer request (input) */ +#define TACK 0x10 /* Transfer acknowledge (output) */ +#define TIP 0x20 /* Transfer in progress (output) */ + +/* Bits in ACR */ +#define SR_CTRL 0x1c /* Shift register control bits */ +#define SR_EXT 0x0c /* Shift on external clock */ +#define SR_OUT 0x10 /* Shift out if 1 */ + +/* Bits in IFR and IER */ +#define IER_SET 0x80 /* set bits in IER */ +#define IER_CLR 0 /* clear bits in IER */ +#define SR_INT 0x04 /* Shift register full/empty */ +#define T1_INT 0x40 /* Timer 1 interrupt */ + +/* Bits in ACR */ +#define T1MODE 0xc0 /* Timer 1 mode */ +#define T1MODE_CONT 0x40 /* continuous interrupts */ + +/* commands (1st byte) */ +#define ADB_PACKET 0 +#define CUDA_PACKET 1 +#define ERROR_PACKET 2 +#define TIMER_PACKET 3 +#define POWER_PACKET 4 +#define MACIIC_PACKET 5 +#define PMU_PACKET 6 + + +/* CUDA commands (2nd byte) */ +#define CUDA_WARM_START 0x0 +#define CUDA_AUTOPOLL 0x1 +#define CUDA_GET_6805_ADDR 0x2 +#define CUDA_GET_TIME 0x3 +#define CUDA_GET_PRAM 0x7 +#define CUDA_SET_6805_ADDR 0x8 +#define CUDA_SET_TIME 0x9 +#define CUDA_POWERDOWN 0xa +#define CUDA_POWERUP_TIME 0xb +#define CUDA_SET_PRAM 0xc +#define CUDA_MS_RESET 0xd +#define CUDA_SEND_DFAC 0xe +#define CUDA_BATTERY_SWAP_SENSE 0x10 +#define CUDA_RESET_SYSTEM 0x11 +#define CUDA_SET_IPL 0x12 +#define CUDA_FILE_SERVER_FLAG 0x13 +#define CUDA_SET_AUTO_RATE 0x14 +#define CUDA_GET_AUTO_RATE 0x16 +#define CUDA_SET_DEVICE_LIST 0x19 +#define CUDA_GET_DEVICE_LIST 0x1a +#define CUDA_SET_ONE_SECOND_MODE 0x1b +#define CUDA_SET_POWER_MESSAGES 0x21 +#define CUDA_GET_SET_IIC 0x22 +#define CUDA_WAKEUP 0x23 +#define CUDA_TIMER_TICKLE 0x24 +#define CUDA_COMBINED_FORMAT_IIC 0x25 + +#define CUDA_TIMER_FREQ (4700000 / 6) +#define CUDA_ADB_POLL_FREQ 50 + +typedef struct CUDATimer { + unsigned int latch; + uint16_t counter_value; /* counter value at load time */ + int64_t load_time; + int64_t next_irq_time; + QEMUTimer *timer; +} CUDATimer; + +typedef struct CUDAState { + /* cuda registers */ + uint8_t b; /* B-side data */ + uint8_t a; /* A-side data */ + uint8_t dirb; /* B-side direction (1=output) */ + uint8_t dira; /* A-side direction (1=output) */ + uint8_t sr; /* Shift register */ + uint8_t acr; /* Auxiliary control register */ + uint8_t pcr; /* Peripheral control register */ + uint8_t ifr; /* Interrupt flag register */ + uint8_t ier; /* Interrupt enable register */ + uint8_t anh; /* A-side data, no handshake */ + + CUDATimer timers[2]; + + uint8_t last_b; /* last value of B register */ + uint8_t last_acr; /* last value of B register */ + + int data_in_size; + int data_in_index; + int data_out_index; + + int irq; + openpic_t *openpic; + uint8_t autopoll; + uint8_t data_in[128]; + uint8_t data_out[16]; + QEMUTimer *adb_poll_timer; +} CUDAState; + +static CUDAState cuda_state; +ADBBusState adb_bus; + +static void cuda_update(CUDAState *s); +static void cuda_receive_packet_from_host(CUDAState *s, + const uint8_t *data, int len); +static void cuda_timer_update(CUDAState *s, CUDATimer *ti, + int64_t current_time); + +static void cuda_update_irq(CUDAState *s) +{ + if (s->ifr & s->ier & (SR_INT | T1_INT)) { + openpic_set_irq(s->openpic, s->irq, 1); + } else { + openpic_set_irq(s->openpic, s->irq, 0); + } +} + +static unsigned int get_counter(CUDATimer *s) +{ + int64_t d; + unsigned int counter; + + d = muldiv64(qemu_get_clock(vm_clock) - s->load_time, + CUDA_TIMER_FREQ, ticks_per_sec); + if (d <= s->counter_value) { + counter = d; + } else { + counter = s->latch - 1 - ((d - s->counter_value) % s->latch); + } + return counter; +} + +static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val) +{ +#ifdef DEBUG_CUDA + printf("cuda: T%d.counter=%d\n", + 1 + (ti->timer == NULL), val); +#endif + ti->load_time = qemu_get_clock(vm_clock); + ti->counter_value = val; + cuda_timer_update(s, ti, ti->load_time); +} + +static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time) +{ + int64_t d, next_time, base; + /* current counter value */ + d = muldiv64(current_time - s->load_time, + CUDA_TIMER_FREQ, ticks_per_sec); + if (d <= s->counter_value) { + next_time = s->counter_value + 1; + } else { + base = ((d - s->counter_value) / s->latch); + base = (base * s->latch) + s->counter_value; + next_time = base + s->latch; + } +#ifdef DEBUG_CUDA + printf("latch=%d counter=%lld delta_next=%lld\n", + s->latch, d, next_time - d); +#endif + next_time = muldiv64(next_time, ticks_per_sec, CUDA_TIMER_FREQ) + + s->load_time; + if (next_time <= current_time) + next_time = current_time + 1; + return next_time; +} + +static void cuda_timer_update(CUDAState *s, CUDATimer *ti, + int64_t current_time) +{ + if (!ti->timer) + return; + if ((s->acr & T1MODE) != T1MODE_CONT) { + qemu_del_timer(ti->timer); + } else { + ti->next_irq_time = get_next_irq_time(ti, current_time); + qemu_mod_timer(ti->timer, ti->next_irq_time); + } +} + +static void cuda_timer1(void *opaque) +{ + CUDAState *s = opaque; + CUDATimer *ti = &s->timers[0]; + + cuda_timer_update(s, ti, ti->next_irq_time); + s->ifr |= T1_INT; + cuda_update_irq(s); +} + +static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr) +{ + CUDAState *s = opaque; + uint32_t val; + + addr = (addr >> 9) & 0xf; + switch(addr) { + case 0: + val = s->b; + break; + case 1: + val = s->a; + break; + case 2: + val = s->dirb; + break; + case 3: + val = s->dira; + break; + case 4: + val = get_counter(&s->timers[0]) & 0xff; + s->ifr &= ~T1_INT; + cuda_update_irq(s); + break; + case 5: + val = get_counter(&s->timers[0]) >> 8; + s->ifr &= ~T1_INT; + cuda_update_irq(s); + break; + case 6: + val = s->timers[0].latch & 0xff; + break; + case 7: + val = (s->timers[0].latch >> 8) & 0xff; + break; + case 8: + val = get_counter(&s->timers[1]) & 0xff; + break; + case 9: + val = get_counter(&s->timers[1]) >> 8; + break; + case 10: + val = s->sr; + s->ifr &= ~SR_INT; + cuda_update_irq(s); + break; + case 11: + val = s->acr; + break; + case 12: + val = s->pcr; + break; + case 13: + val = s->ifr; + break; + case 14: + val = s->ier; + break; + default: + case 15: + val = s->anh; + break; + } +#ifdef DEBUG_CUDA + if (addr != 13 || val != 0) + printf("cuda: read: reg=0x%x val=%02x\n", addr, val); +#endif + return val; +} + +static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + CUDAState *s = opaque; + + addr = (addr >> 9) & 0xf; +#ifdef DEBUG_CUDA + printf("cuda: write: reg=0x%x val=%02x\n", addr, val); +#endif + + switch(addr) { + case 0: + s->b = val; + cuda_update(s); + break; + case 1: + s->a = val; + break; + case 2: + s->dirb = val; + break; + case 3: + s->dira = val; + break; + case 4: + val = val | (get_counter(&s->timers[0]) & 0xff00); + set_counter(s, &s->timers[0], val); + break; + case 5: + val = (val << 8) | (get_counter(&s->timers[0]) & 0xff); + set_counter(s, &s->timers[0], val); + break; + case 6: + s->timers[0].latch = (s->timers[0].latch & 0xff00) | val; + cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock)); + break; + case 7: + s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8); + cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock)); + break; + case 8: + val = val | (get_counter(&s->timers[1]) & 0xff00); + set_counter(s, &s->timers[1], val); + break; + case 9: + val = (val << 8) | (get_counter(&s->timers[1]) & 0xff); + set_counter(s, &s->timers[1], val); + break; + case 10: + s->sr = val; + break; + case 11: + s->acr = val; + cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock)); + cuda_update(s); + break; + case 12: + s->pcr = val; + break; + case 13: + /* reset bits */ + s->ifr &= ~val; + cuda_update_irq(s); + break; + case 14: + if (val & IER_SET) { + /* set bits */ + s->ier |= val & 0x7f; + } else { + /* reset bits */ + s->ier &= ~val; + } + cuda_update_irq(s); + break; + default: + case 15: + s->anh = val; + break; + } +} + +/* NOTE: TIP and TREQ are negated */ +static void cuda_update(CUDAState *s) +{ + int packet_received, len; + + packet_received = 0; + if (!(s->b & TIP)) { + /* transfer requested from host */ + + if (s->acr & SR_OUT) { + /* data output */ + if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) { + if (s->data_out_index < sizeof(s->data_out)) { +#ifdef DEBUG_CUDA + printf("cuda: send: %02x\n", s->sr); +#endif + s->data_out[s->data_out_index++] = s->sr; + s->ifr |= SR_INT; + cuda_update_irq(s); + } + } + } else { + if (s->data_in_index < s->data_in_size) { + /* data input */ + if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) { + s->sr = s->data_in[s->data_in_index++]; +#ifdef DEBUG_CUDA + printf("cuda: recv: %02x\n", s->sr); +#endif + /* indicate end of transfer */ + if (s->data_in_index >= s->data_in_size) { + s->b = (s->b | TREQ); + } + s->ifr |= SR_INT; + cuda_update_irq(s); + } + } + } + } else { + /* no transfer requested: handle sync case */ + if ((s->last_b & TIP) && (s->b & TACK) != (s->last_b & TACK)) { + /* update TREQ state each time TACK change state */ + if (s->b & TACK) + s->b = (s->b | TREQ); + else + s->b = (s->b & ~TREQ); + s->ifr |= SR_INT; + cuda_update_irq(s); + } else { + if (!(s->last_b & TIP)) { + /* handle end of host to cuda transfert */ + packet_received = (s->data_out_index > 0); + /* always an IRQ at the end of transfert */ + s->ifr |= SR_INT; + cuda_update_irq(s); + } + /* signal if there is data to read */ + if (s->data_in_index < s->data_in_size) { + s->b = (s->b & ~TREQ); + } + } + } + + s->last_acr = s->acr; + s->last_b = s->b; + + /* NOTE: cuda_receive_packet_from_host() can call cuda_update() + recursively */ + if (packet_received) { + len = s->data_out_index; + s->data_out_index = 0; + cuda_receive_packet_from_host(s, s->data_out, len); + } +} + +static void cuda_send_packet_to_host(CUDAState *s, + const uint8_t *data, int len) +{ +#ifdef DEBUG_CUDA_PACKET + { + int i; + printf("cuda_send_packet_to_host:\n"); + for(i = 0; i < len; i++) + printf(" %02x", data[i]); + printf("\n"); + } +#endif + memcpy(s->data_in, data, len); + s->data_in_size = len; + s->data_in_index = 0; + cuda_update(s); + s->ifr |= SR_INT; + cuda_update_irq(s); +} + +static void cuda_adb_poll(void *opaque) +{ + CUDAState *s = opaque; + uint8_t obuf[ADB_MAX_OUT_LEN + 2]; + int olen; + + olen = adb_poll(&adb_bus, obuf + 2); + if (olen > 0) { + obuf[0] = ADB_PACKET; + obuf[1] = 0x40; /* polled data */ + cuda_send_packet_to_host(s, obuf, olen + 2); + } + qemu_mod_timer(s->adb_poll_timer, + qemu_get_clock(vm_clock) + + (ticks_per_sec / CUDA_ADB_POLL_FREQ)); +} + +static void cuda_receive_packet(CUDAState *s, + const uint8_t *data, int len) +{ + uint8_t obuf[16]; + int ti, autopoll; + + switch(data[0]) { + case CUDA_AUTOPOLL: + autopoll = (data[1] != 0); + if (autopoll != s->autopoll) { + s->autopoll = autopoll; + if (autopoll) { + qemu_mod_timer(s->adb_poll_timer, + qemu_get_clock(vm_clock) + + (ticks_per_sec / CUDA_ADB_POLL_FREQ)); + } else { + qemu_del_timer(s->adb_poll_timer); + } + } + obuf[0] = CUDA_PACKET; + obuf[1] = data[1]; + cuda_send_packet_to_host(s, obuf, 2); + break; + case CUDA_GET_TIME: + /* XXX: add time support ? */ + ti = time(NULL); + obuf[0] = CUDA_PACKET; + obuf[1] = 0; + obuf[2] = 0; + obuf[3] = ti >> 24; + obuf[4] = ti >> 16; + obuf[5] = ti >> 8; + obuf[6] = ti; + cuda_send_packet_to_host(s, obuf, 7); + break; + case CUDA_SET_TIME: + case CUDA_FILE_SERVER_FLAG: + case CUDA_SET_DEVICE_LIST: + case CUDA_SET_AUTO_RATE: + case CUDA_SET_POWER_MESSAGES: + obuf[0] = CUDA_PACKET; + obuf[1] = 0; + cuda_send_packet_to_host(s, obuf, 2); + break; + default: + break; + } +} + +static void cuda_receive_packet_from_host(CUDAState *s, + const uint8_t *data, int len) +{ +#ifdef DEBUG_CUDA_PACKET + { + int i; + printf("cuda_receive_packet_to_host:\n"); + for(i = 0; i < len; i++) + printf(" %02x", data[i]); + printf("\n"); + } +#endif + switch(data[0]) { + case ADB_PACKET: + { + uint8_t obuf[ADB_MAX_OUT_LEN + 2]; + int olen; + olen = adb_request(&adb_bus, obuf + 2, data + 1, len - 1); + if (olen > 0) { + obuf[0] = ADB_PACKET; + obuf[1] = 0x00; + } else { + /* error */ + obuf[0] = ADB_PACKET; + obuf[1] = -olen; + olen = 0; + } + cuda_send_packet_to_host(s, obuf, olen + 2); + } + break; + case CUDA_PACKET: + cuda_receive_packet(s, data + 1, len - 1); + break; + } +} + +static void cuda_writew (void *opaque, target_phys_addr_t addr, uint32_t value) +{ +} + +static void cuda_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +{ +} + +static uint32_t cuda_readw (void *opaque, target_phys_addr_t addr) +{ + return 0; +} + +static uint32_t cuda_readl (void *opaque, target_phys_addr_t addr) +{ + return 0; +} + +static CPUWriteMemoryFunc *cuda_write[] = { + &cuda_writeb, + &cuda_writew, + &cuda_writel, +}; + +static CPUReadMemoryFunc *cuda_read[] = { + &cuda_readb, + &cuda_readw, + &cuda_readl, +}; + +int cuda_init(openpic_t *openpic, int irq) +{ + CUDAState *s = &cuda_state; + int cuda_mem_index; + + s->openpic = openpic; + s->irq = irq; + + s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s); + s->timers[0].latch = 0x10000; + set_counter(s, &s->timers[0], 0xffff); + s->timers[1].latch = 0x10000; + s->ier = T1_INT | SR_INT; + set_counter(s, &s->timers[1], 0xffff); + + s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s); + cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s); + return cuda_mem_index; +} diff --git a/tools/ioemu/hw/dma.c b/tools/ioemu/hw/dma.c new file mode 100644 index 0000000000..ce828699f0 --- /dev/null +++ b/tools/ioemu/hw/dma.c @@ -0,0 +1,535 @@ +/* + * QEMU DMA emulation + * + * Copyright (c) 2003-2004 Vassili Karpov (malc) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +/* #define DEBUG_DMA */ + +#define dolog(...) fprintf (stderr, "dma: " __VA_ARGS__) +#ifdef DEBUG_DMA +#define lwarn(...) fprintf (stderr, "dma: " __VA_ARGS__) +#define linfo(...) fprintf (stderr, "dma: " __VA_ARGS__) +#define ldebug(...) fprintf (stderr, "dma: " __VA_ARGS__) +#else +#define lwarn(...) +#define linfo(...) +#define ldebug(...) +#endif + +#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0]))) + +struct dma_regs { + int now[2]; + uint16_t base[2]; + uint8_t mode; + uint8_t page; + uint8_t pageh; + uint8_t dack; + uint8_t eop; + DMA_transfer_handler transfer_handler; + void *opaque; +}; + +#define ADDR 0 +#define COUNT 1 + +static struct dma_cont { + uint8_t status; + uint8_t command; + uint8_t mask; + uint8_t flip_flop; + int dshift; + struct dma_regs regs[4]; +} dma_controllers[2]; + +enum { + CMD_MEMORY_TO_MEMORY = 0x01, + CMD_FIXED_ADDRESS = 0x02, + CMD_BLOCK_CONTROLLER = 0x04, + CMD_COMPRESSED_TIME = 0x08, + CMD_CYCLIC_PRIORITY = 0x10, + CMD_EXTENDED_WRITE = 0x20, + CMD_LOW_DREQ = 0x40, + CMD_LOW_DACK = 0x80, + CMD_NOT_SUPPORTED = CMD_MEMORY_TO_MEMORY | CMD_FIXED_ADDRESS + | CMD_COMPRESSED_TIME | CMD_CYCLIC_PRIORITY | CMD_EXTENDED_WRITE + | CMD_LOW_DREQ | CMD_LOW_DACK + +}; + +static int channels[8] = {-1, 2, 3, 1, -1, -1, -1, 0}; + +static void write_page (void *opaque, uint32_t nport, uint32_t data) +{ + struct dma_cont *d = opaque; + int ichan; + + ichan = channels[nport & 7]; + if (-1 == ichan) { + dolog ("invalid channel %#x %#x\n", nport, data); + return; + } + d->regs[ichan].page = data; +} + +static void write_pageh (void *opaque, uint32_t nport, uint32_t data) +{ + struct dma_cont *d = opaque; + int ichan; + + ichan = channels[nport & 7]; + if (-1 == ichan) { + dolog ("invalid channel %#x %#x\n", nport, data); + return; + } + d->regs[ichan].pageh = data; +} + +static uint32_t read_page (void *opaque, uint32_t nport) +{ + struct dma_cont *d = opaque; + int ichan; + + ichan = channels[nport & 7]; + if (-1 == ichan) { + dolog ("invalid channel read %#x\n", nport); + return 0; + } + return d->regs[ichan].page; +} + +static uint32_t read_pageh (void *opaque, uint32_t nport) +{ + struct dma_cont *d = opaque; + int ichan; + + ichan = channels[nport & 7]; + if (-1 == ichan) { + dolog ("invalid channel read %#x\n", nport); + return 0; + } + return d->regs[ichan].pageh; +} + +static inline void init_chan (struct dma_cont *d, int ichan) +{ + struct dma_regs *r; + + r = d->regs + ichan; + r->now[ADDR] = r->base[ADDR] << d->dshift; + r->now[COUNT] = 0; +} + +static inline int getff (struct dma_cont *d) +{ + int ff; + + ff = d->flip_flop; + d->flip_flop = !ff; + return ff; +} + +static uint32_t read_chan (void *opaque, uint32_t nport) +{ + struct dma_cont *d = opaque; + int ichan, nreg, iport, ff, val, dir; + struct dma_regs *r; + + iport = (nport >> d->dshift) & 0x0f; + ichan = iport >> 1; + nreg = iport & 1; + r = d->regs + ichan; + + dir = ((r->mode >> 5) & 1) ? -1 : 1; + ff = getff (d); + if (nreg) + val = (r->base[COUNT] << d->dshift) - r->now[COUNT]; + else + val = r->now[ADDR] + r->now[COUNT] * dir; + + ldebug ("read_chan %#x -> %d\n", iport, val); + return (val >> (d->dshift + (ff << 3))) & 0xff; +} + +static void write_chan (void *opaque, uint32_t nport, uint32_t data) +{ + struct dma_cont *d = opaque; + int iport, ichan, nreg; + struct dma_regs *r; + + iport = (nport >> d->dshift) & 0x0f; + ichan = iport >> 1; + nreg = iport & 1; + r = d->regs + ichan; + if (getff (d)) { + r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00); + init_chan (d, ichan); + } else { + r->base[nreg] = (r->base[nreg] & 0xff00) | (data & 0xff); + } +} + +static void write_cont (void *opaque, uint32_t nport, uint32_t data) +{ + struct dma_cont *d = opaque; + int iport, ichan = 0; + + iport = (nport >> d->dshift) & 0x0f; + switch (iport) { + case 0x08: /* command */ + if ((data != 0) && (data & CMD_NOT_SUPPORTED)) { + dolog ("command %#x not supported\n", data); + return; + } + d->command = data; + break; + + case 0x09: + ichan = data & 3; + if (data & 4) { + d->status |= 1 << (ichan + 4); + } + else { + d->status &= ~(1 << (ichan + 4)); + } + d->status &= ~(1 << ichan); + break; + + case 0x0a: /* single mask */ + if (data & 4) + d->mask |= 1 << (data & 3); + else + d->mask &= ~(1 << (data & 3)); + break; + + case 0x0b: /* mode */ + { + ichan = data & 3; +#ifdef DEBUG_DMA + { + int op, ai, dir, opmode; + op = (data >> 2) & 3; + ai = (data >> 4) & 1; + dir = (data >> 5) & 1; + opmode = (data >> 6) & 3; + + linfo ("ichan %d, op %d, ai %d, dir %d, opmode %d\n", + ichan, op, ai, dir, opmode); + } +#endif + d->regs[ichan].mode = data; + break; + } + + case 0x0c: /* clear flip flop */ + d->flip_flop = 0; + break; + + case 0x0d: /* reset */ + d->flip_flop = 0; + d->mask = ~0; + d->status = 0; + d->command = 0; + break; + + case 0x0e: /* clear mask for all channels */ + d->mask = 0; + break; + + case 0x0f: /* write mask for all channels */ + d->mask = data; + break; + + default: + dolog ("unknown iport %#x\n", iport); + break; + } + +#ifdef DEBUG_DMA + if (0xc != iport) { + linfo ("write_cont: nport %#06x, ichan % 2d, val %#06x\n", + nport, ichan, data); + } +#endif +} + +static uint32_t read_cont (void *opaque, uint32_t nport) +{ + struct dma_cont *d = opaque; + int iport, val; + + iport = (nport >> d->dshift) & 0x0f; + switch (iport) { + case 0x08: /* status */ + val = d->status; + d->status &= 0xf0; + break; + case 0x0f: /* mask */ + val = d->mask; + break; + default: + val = 0; + break; + } + + ldebug ("read_cont: nport %#06x, iport %#04x val %#x\n", nport, iport, val); + return val; +} + +int DMA_get_channel_mode (int nchan) +{ + return dma_controllers[nchan > 3].regs[nchan & 3].mode; +} + +void DMA_hold_DREQ (int nchan) +{ + int ncont, ichan; + + ncont = nchan > 3; + ichan = nchan & 3; + linfo ("held cont=%d chan=%d\n", ncont, ichan); + dma_controllers[ncont].status |= 1 << (ichan + 4); +} + +void DMA_release_DREQ (int nchan) +{ + int ncont, ichan; + + ncont = nchan > 3; + ichan = nchan & 3; + linfo ("released cont=%d chan=%d\n", ncont, ichan); + dma_controllers[ncont].status &= ~(1 << (ichan + 4)); +} + +static void channel_run (int ncont, int ichan) +{ + int n; + struct dma_regs *r = &dma_controllers[ncont].regs[ichan]; +#ifdef DEBUG_DMA + int dir, opmode; + + dir = (r->mode >> 5) & 1; + opmode = (r->mode >> 6) & 3; + + if (dir) { + dolog ("DMA in address decrement mode\n"); + } + if (opmode != 1) { + dolog ("DMA not in single mode select %#x\n", opmode); + } +#endif + + r = dma_controllers[ncont].regs + ichan; + n = r->transfer_handler (r->opaque, ichan + (ncont << 2), + r->now[COUNT], (r->base[COUNT] + 1) << ncont); + r->now[COUNT] = n; + ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont); +} + +void DMA_run (void) +{ + struct dma_cont *d; + int icont, ichan; + + d = dma_controllers; + + for (icont = 0; icont < 2; icont++, d++) { + for (ichan = 0; ichan < 4; ichan++) { + int mask; + + mask = 1 << ichan; + + if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4)))) + channel_run (icont, ichan); + } + } +} + +void DMA_register_channel (int nchan, + DMA_transfer_handler transfer_handler, + void *opaque) +{ + struct dma_regs *r; + int ichan, ncont; + + ncont = nchan > 3; + ichan = nchan & 3; + + r = dma_controllers[ncont].regs + ichan; + r->transfer_handler = transfer_handler; + r->opaque = opaque; +} + +int DMA_read_memory (int nchan, void *buf, int pos, int len) +{ + struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3]; + target_ulong addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR]; + + if (r->mode & 0x20) { + int i; + uint8_t *p = buf; + + cpu_physical_memory_read (addr - pos - len, buf, len); + /* What about 16bit transfers? */ + for (i = 0; i < len >> 1; i++) { + uint8_t b = p[len - i - 1]; + p[i] = b; + } + } + else + cpu_physical_memory_read (addr + pos, buf, len); + + return len; +} + +int DMA_write_memory (int nchan, void *buf, int pos, int len) +{ + struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3]; + target_ulong addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR]; + + if (r->mode & 0x20) { + int i; + uint8_t *p = buf; + + cpu_physical_memory_write (addr - pos - len, buf, len); + /* What about 16bit transfers? */ + for (i = 0; i < len; i++) { + uint8_t b = p[len - i - 1]; + p[i] = b; + } + } + else + cpu_physical_memory_write (addr + pos, buf, len); + + return len; +} + +/* request the emulator to transfer a new DMA memory block ASAP */ +void DMA_schedule(int nchan) +{ + cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); +} + +static void dma_reset(void *opaque) +{ + struct dma_cont *d = opaque; + write_cont (d, (0x0d << d->dshift), 0); +} + +/* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */ +static void dma_init2(struct dma_cont *d, int base, int dshift, + int page_base, int pageh_base) +{ + const static int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 }; + int i; + + d->dshift = dshift; + for (i = 0; i < 8; i++) { + register_ioport_write (base + (i << dshift), 1, 1, write_chan, d); + register_ioport_read (base + (i << dshift), 1, 1, read_chan, d); + } + for (i = 0; i < LENOFA (page_port_list); i++) { + register_ioport_write (page_base + page_port_list[i], 1, 1, + write_page, d); + register_ioport_read (page_base + page_port_list[i], 1, 1, + read_page, d); + if (pageh_base >= 0) { + register_ioport_write (pageh_base + page_port_list[i], 1, 1, + write_pageh, d); + register_ioport_read (pageh_base + page_port_list[i], 1, 1, + read_pageh, d); + } + } + for (i = 0; i < 8; i++) { + register_ioport_write (base + ((i + 8) << dshift), 1, 1, + write_cont, d); + register_ioport_read (base + ((i + 8) << dshift), 1, 1, + read_cont, d); + } + qemu_register_reset(dma_reset, d); + dma_reset(d); +} + +static void dma_save (QEMUFile *f, void *opaque) +{ + struct dma_cont *d = opaque; + int i; + + /* qemu_put_8s (f, &d->status); */ + qemu_put_8s (f, &d->command); + qemu_put_8s (f, &d->mask); + qemu_put_8s (f, &d->flip_flop); + qemu_put_be32s (f, &d->dshift); + + for (i = 0; i < 4; ++i) { + struct dma_regs *r = &d->regs[i]; + qemu_put_be32s (f, &r->now[0]); + qemu_put_be32s (f, &r->now[1]); + qemu_put_be16s (f, &r->base[0]); + qemu_put_be16s (f, &r->base[1]); + qemu_put_8s (f, &r->mode); + qemu_put_8s (f, &r->page); + qemu_put_8s (f, &r->pageh); + qemu_put_8s (f, &r->dack); + qemu_put_8s (f, &r->eop); + } +} + +static int dma_load (QEMUFile *f, void *opaque, int version_id) +{ + struct dma_cont *d = opaque; + int i; + + if (version_id != 1) + return -EINVAL; + + /* qemu_get_8s (f, &d->status); */ + qemu_get_8s (f, &d->command); + qemu_get_8s (f, &d->mask); + qemu_get_8s (f, &d->flip_flop); + qemu_get_be32s (f, &d->dshift); + + for (i = 0; i < 4; ++i) { + struct dma_regs *r = &d->regs[i]; + qemu_get_be32s (f, &r->now[0]); + qemu_get_be32s (f, &r->now[1]); + qemu_get_be16s (f, &r->base[0]); + qemu_get_be16s (f, &r->base[1]); + qemu_get_8s (f, &r->mode); + qemu_get_8s (f, &r->page); + qemu_get_8s (f, &r->pageh); + qemu_get_8s (f, &r->dack); + qemu_get_8s (f, &r->eop); + } + return 0; +} + +void DMA_init (int high_page_enable) +{ + dma_init2(&dma_controllers[0], 0x00, 0, 0x80, + high_page_enable ? 0x480 : -1); + dma_init2(&dma_controllers[1], 0xc0, 1, 0x88, + high_page_enable ? 0x488 : -1); + register_savevm ("dma", 0, 1, dma_save, dma_load, &dma_controllers[0]); + register_savevm ("dma", 1, 1, dma_save, dma_load, &dma_controllers[1]); +} diff --git a/tools/ioemu/hw/fdc.c b/tools/ioemu/hw/fdc.c new file mode 100644 index 0000000000..d512b1ca98 --- /dev/null +++ b/tools/ioemu/hw/fdc.c @@ -0,0 +1,1719 @@ +/* + * QEMU Floppy disk emulator (Intel 82078) + * + * Copyright (c) 2003 Jocelyn Mayer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +/********************************************************/ +/* debug Floppy devices */ +//#define DEBUG_FLOPPY + +#ifdef DEBUG_FLOPPY +#define FLOPPY_DPRINTF(fmt, args...) \ +do { printf("FLOPPY: " fmt , ##args); } while (0) +#else +#define FLOPPY_DPRINTF(fmt, args...) +#endif + +#define FLOPPY_ERROR(fmt, args...) \ +do { printf("FLOPPY ERROR: %s: " fmt, __func__ , ##args); } while (0) + +/********************************************************/ +/* Floppy drive emulation */ + +/* Will always be a fixed parameter for us */ +#define FD_SECTOR_LEN 512 +#define FD_SECTOR_SC 2 /* Sector size code */ + +/* Floppy disk drive emulation */ +typedef enum fdisk_type_t { + FDRIVE_DISK_288 = 0x01, /* 2.88 MB disk */ + FDRIVE_DISK_144 = 0x02, /* 1.44 MB disk */ + FDRIVE_DISK_720 = 0x03, /* 720 kB disk */ + FDRIVE_DISK_USER = 0x04, /* User defined geometry */ + FDRIVE_DISK_NONE = 0x05, /* No disk */ +} fdisk_type_t; + +typedef enum fdrive_type_t { + FDRIVE_DRV_144 = 0x00, /* 1.44 MB 3"5 drive */ + FDRIVE_DRV_288 = 0x01, /* 2.88 MB 3"5 drive */ + FDRIVE_DRV_120 = 0x02, /* 1.2 MB 5"25 drive */ + FDRIVE_DRV_NONE = 0x03, /* No drive connected */ +} fdrive_type_t; + +typedef enum fdrive_flags_t { + FDRIVE_MOTOR_ON = 0x01, /* motor on/off */ + FDRIVE_REVALIDATE = 0x02, /* Revalidated */ +} fdrive_flags_t; + +typedef enum fdisk_flags_t { + FDISK_DBL_SIDES = 0x01, +} fdisk_flags_t; + +typedef struct fdrive_t { + BlockDriverState *bs; + /* Drive status */ + fdrive_type_t drive; + fdrive_flags_t drflags; + uint8_t perpendicular; /* 2.88 MB access mode */ + /* Position */ + uint8_t head; + uint8_t track; + uint8_t sect; + /* Last operation status */ + uint8_t dir; /* Direction */ + uint8_t rw; /* Read/write */ + /* Media */ + fdisk_flags_t flags; + uint8_t last_sect; /* Nb sector per track */ + uint8_t max_track; /* Nb of tracks */ + uint16_t bps; /* Bytes per sector */ + uint8_t ro; /* Is read-only */ +} fdrive_t; + +static void fd_init (fdrive_t *drv, BlockDriverState *bs) +{ + /* Drive */ + drv->bs = bs; + drv->drive = FDRIVE_DRV_NONE; + drv->drflags = 0; + drv->perpendicular = 0; + /* Disk */ + drv->last_sect = 0; + drv->max_track = 0; +} + +static int _fd_sector (uint8_t head, uint8_t track, + uint8_t sect, uint8_t last_sect) +{ + return (((track * 2) + head) * last_sect) + sect - 1; +} + +/* Returns current position, in sectors, for given drive */ +static int fd_sector (fdrive_t *drv) +{ + return _fd_sector(drv->head, drv->track, drv->sect, drv->last_sect); +} + +static int fd_seek (fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect, + int enable_seek) +{ + uint32_t sector; + int ret; + + if (track > drv->max_track || + (head != 0 && (drv->flags & FDISK_DBL_SIDES) == 0)) { + FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n", + head, track, sect, 1, + (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1, + drv->max_track, drv->last_sect); + return 2; + } + if (sect > drv->last_sect) { + FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n", + head, track, sect, 1, + (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1, + drv->max_track, drv->last_sect); + return 3; + } + sector = _fd_sector(head, track, sect, drv->last_sect); + ret = 0; + if (sector != fd_sector(drv)) { +#if 0 + if (!enable_seek) { + FLOPPY_ERROR("no implicit seek %d %02x %02x (max=%d %02x %02x)\n", + head, track, sect, 1, drv->max_track, drv->last_sect); + return 4; + } +#endif + drv->head = head; + if (drv->track != track) + ret = 1; + drv->track = track; + drv->sect = sect; + } + + return ret; +} + +/* Set drive back to track 0 */ +static void fd_recalibrate (fdrive_t *drv) +{ + FLOPPY_DPRINTF("recalibrate\n"); + drv->head = 0; + drv->track = 0; + drv->sect = 1; + drv->dir = 1; + drv->rw = 0; +} + +/* Recognize floppy formats */ +typedef struct fd_format_t { + fdrive_type_t drive; + fdisk_type_t disk; + uint8_t last_sect; + uint8_t max_track; + uint8_t max_head; + const unsigned char *str; +} fd_format_t; + +static fd_format_t fd_formats[] = { + /* First entry is default format */ + /* 1.44 MB 3"1/2 floppy disks */ + { FDRIVE_DRV_144, FDRIVE_DISK_144, 18, 80, 1, "1.44 MB 3\"1/2", }, + { FDRIVE_DRV_144, FDRIVE_DISK_144, 20, 80, 1, "1.6 MB 3\"1/2", }, + { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 80, 1, "1.68 MB 3\"1/2", }, + { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 82, 1, "1.72 MB 3\"1/2", }, + { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 83, 1, "1.74 MB 3\"1/2", }, + { FDRIVE_DRV_144, FDRIVE_DISK_144, 22, 80, 1, "1.76 MB 3\"1/2", }, + { FDRIVE_DRV_144, FDRIVE_DISK_144, 23, 80, 1, "1.84 MB 3\"1/2", }, + { FDRIVE_DRV_144, FDRIVE_DISK_144, 24, 80, 1, "1.92 MB 3\"1/2", }, + /* 2.88 MB 3"1/2 floppy disks */ + { FDRIVE_DRV_288, FDRIVE_DISK_288, 36, 80, 1, "2.88 MB 3\"1/2", }, + { FDRIVE_DRV_288, FDRIVE_DISK_288, 39, 80, 1, "3.12 MB 3\"1/2", }, + { FDRIVE_DRV_288, FDRIVE_DISK_288, 40, 80, 1, "3.2 MB 3\"1/2", }, + { FDRIVE_DRV_288, FDRIVE_DISK_288, 44, 80, 1, "3.52 MB 3\"1/2", }, + { FDRIVE_DRV_288, FDRIVE_DISK_288, 48, 80, 1, "3.84 MB 3\"1/2", }, + /* 720 kB 3"1/2 floppy disks */ + { FDRIVE_DRV_144, FDRIVE_DISK_720, 9, 80, 1, "720 kB 3\"1/2", }, + { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 80, 1, "800 kB 3\"1/2", }, + { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 82, 1, "820 kB 3\"1/2", }, + { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 83, 1, "830 kB 3\"1/2", }, + { FDRIVE_DRV_144, FDRIVE_DISK_720, 13, 80, 1, "1.04 MB 3\"1/2", }, + { FDRIVE_DRV_144, FDRIVE_DISK_720, 14, 80, 1, "1.12 MB 3\"1/2", }, + /* 1.2 MB 5"1/4 floppy disks */ + { FDRIVE_DRV_120, FDRIVE_DISK_288, 15, 80, 1, "1.2 kB 5\"1/4", }, + { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 80, 1, "1.44 MB 5\"1/4", }, + { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 82, 1, "1.48 MB 5\"1/4", }, + { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 83, 1, "1.49 MB 5\"1/4", }, + { FDRIVE_DRV_120, FDRIVE_DISK_288, 20, 80, 1, "1.6 MB 5\"1/4", }, + /* 720 kB 5"1/4 floppy disks */ + { FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 80, 1, "720 kB 5\"1/4", }, + { FDRIVE_DRV_120, FDRIVE_DISK_288, 11, 80, 1, "880 kB 5\"1/4", }, + /* 360 kB 5"1/4 floppy disks */ + { FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 40, 1, "360 kB 5\"1/4", }, + { FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 40, 0, "180 kB 5\"1/4", }, + { FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 41, 1, "410 kB 5\"1/4", }, + { FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 42, 1, "420 kB 5\"1/4", }, + /* 320 kB 5"1/4 floppy disks */ + { FDRIVE_DRV_120, FDRIVE_DISK_288, 8, 40, 1, "320 kB 5\"1/4", }, + { FDRIVE_DRV_120, FDRIVE_DISK_288, 8, 40, 0, "160 kB 5\"1/4", }, + /* 360 kB must match 5"1/4 better than 3"1/2... */ + { FDRIVE_DRV_144, FDRIVE_DISK_720, 9, 80, 0, "360 kB 3\"1/2", }, + /* end */ + { FDRIVE_DRV_NONE, FDRIVE_DISK_NONE, -1, -1, 0, NULL, }, +}; + +/* Revalidate a disk drive after a disk change */ +static void fd_revalidate (fdrive_t *drv) +{ + fd_format_t *parse; + int64_t nb_sectors, size; + int i, first_match, match; + int nb_heads, max_track, last_sect, ro; + + FLOPPY_DPRINTF("revalidate\n"); + drv->drflags &= ~FDRIVE_REVALIDATE; + if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) { + ro = bdrv_is_read_only(drv->bs); + bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect); + if (nb_heads != 0 && max_track != 0 && last_sect != 0) { + FLOPPY_DPRINTF("User defined disk (%d %d %d)", + nb_heads - 1, max_track, last_sect); + } else { + bdrv_get_geometry(drv->bs, &nb_sectors); + match = -1; + first_match = -1; + for (i = 0;; i++) { + parse = &fd_formats[i]; + if (parse->drive == FDRIVE_DRV_NONE) + break; + if (drv->drive == parse->drive || + drv->drive == FDRIVE_DRV_NONE) { + size = (parse->max_head + 1) * parse->max_track * + parse->last_sect; + if (nb_sectors == size) { + match = i; + break; + } + if (first_match == -1) + first_match = i; + } + } + if (match == -1) { + if (first_match == -1) + match = 1; + else + match = first_match; + parse = &fd_formats[match]; + } + nb_heads = parse->max_head + 1; + max_track = parse->max_track; + last_sect = parse->last_sect; + drv->drive = parse->drive; + FLOPPY_DPRINTF("%s floppy disk (%d h %d t %d s) %s\n", parse->str, + nb_heads, max_track, last_sect, ro ? "ro" : "rw"); + } + if (nb_heads == 1) { + drv->flags &= ~FDISK_DBL_SIDES; + } else { + drv->flags |= FDISK_DBL_SIDES; + } + drv->max_track = max_track; + drv->last_sect = last_sect; + drv->ro = ro; + } else { + FLOPPY_DPRINTF("No disk in drive\n"); + drv->last_sect = 0; + drv->max_track = 0; + drv->flags &= ~FDISK_DBL_SIDES; + } + drv->drflags |= FDRIVE_REVALIDATE; +} + +/* Motor control */ +static void fd_start (fdrive_t *drv) +{ + drv->drflags |= FDRIVE_MOTOR_ON; +} + +static void fd_stop (fdrive_t *drv) +{ + drv->drflags &= ~FDRIVE_MOTOR_ON; +} + +/* Re-initialise a drives (motor off, repositioned) */ +static void fd_reset (fdrive_t *drv) +{ + fd_stop(drv); + fd_recalibrate(drv); +} + +/********************************************************/ +/* Intel 82078 floppy disk controller emulation */ + +static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq); +static void fdctrl_reset_fifo (fdctrl_t *fdctrl); +static int fdctrl_transfer_handler (void *opaque, int nchan, + int dma_pos, int dma_len); +static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status); +static void fdctrl_result_timer(void *opaque); + +static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl); +static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl); +static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value); +static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl); +static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value); +static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl); +static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value); +static uint32_t fdctrl_read_data (fdctrl_t *fdctrl); +static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value); +static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl); + +enum { + FD_CTRL_ACTIVE = 0x01, /* XXX: suppress that */ + FD_CTRL_RESET = 0x02, + FD_CTRL_SLEEP = 0x04, /* XXX: suppress that */ + FD_CTRL_BUSY = 0x08, /* dma transfer in progress */ + FD_CTRL_INTR = 0x10, +}; + +enum { + FD_DIR_WRITE = 0, + FD_DIR_READ = 1, + FD_DIR_SCANE = 2, + FD_DIR_SCANL = 3, + FD_DIR_SCANH = 4, +}; + +enum { + FD_STATE_CMD = 0x00, + FD_STATE_STATUS = 0x01, + FD_STATE_DATA = 0x02, + FD_STATE_STATE = 0x03, + FD_STATE_MULTI = 0x10, + FD_STATE_SEEK = 0x20, + FD_STATE_FORMAT = 0x40, +}; + +#define FD_STATE(state) ((state) & FD_STATE_STATE) +#define FD_SET_STATE(state, new_state) \ +do { (state) = ((state) & ~FD_STATE_STATE) | (new_state); } while (0) +#define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI) +#define FD_DID_SEEK(state) ((state) & FD_STATE_SEEK) +#define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT) + +struct fdctrl_t { + fdctrl_t *fdctrl; + /* Controller's identification */ + uint8_t version; + /* HW */ + int irq_lvl; + int dma_chann; + uint32_t io_base; + /* Controller state */ + QEMUTimer *result_timer; + uint8_t state; + uint8_t dma_en; + uint8_t cur_drv; + uint8_t bootsel; + /* Command FIFO */ + uint8_t fifo[FD_SECTOR_LEN]; + uint32_t data_pos; + uint32_t data_len; + uint8_t data_state; + uint8_t data_dir; + uint8_t int_status; + uint8_t eot; /* last wanted sector */ + /* States kept only to be returned back */ + /* Timers state */ + uint8_t timer0; + uint8_t timer1; + /* precompensation */ + uint8_t precomp_trk; + uint8_t config; + uint8_t lock; + /* Power down config (also with status regB access mode */ + uint8_t pwrd; + /* Floppy drives */ + fdrive_t drives[2]; +}; + +static uint32_t fdctrl_read (void *opaque, uint32_t reg) +{ + fdctrl_t *fdctrl = opaque; + uint32_t retval; + + switch (reg & 0x07) { + case 0x01: + retval = fdctrl_read_statusB(fdctrl); + break; + case 0x02: + retval = fdctrl_read_dor(fdctrl); + break; + case 0x03: + retval = fdctrl_read_tape(fdctrl); + break; + case 0x04: + retval = fdctrl_read_main_status(fdctrl); + break; + case 0x05: + retval = fdctrl_read_data(fdctrl); + break; + case 0x07: + retval = fdctrl_read_dir(fdctrl); + break; + default: + retval = (uint32_t)(-1); + break; + } + FLOPPY_DPRINTF("read reg%d: 0x%02x\n", reg & 7, retval); + + return retval; +} + +static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value) +{ + fdctrl_t *fdctrl = opaque; + + FLOPPY_DPRINTF("write reg%d: 0x%02x\n", reg & 7, value); + + switch (reg & 0x07) { + case 0x02: + fdctrl_write_dor(fdctrl, value); + break; + case 0x03: + fdctrl_write_tape(fdctrl, value); + break; + case 0x04: + fdctrl_write_rate(fdctrl, value); + break; + case 0x05: + fdctrl_write_data(fdctrl, value); + break; + default: + break; + } +} + +static void fd_change_cb (void *opaque) +{ + fdrive_t *drv = opaque; + + FLOPPY_DPRINTF("disk change\n"); + fd_revalidate(drv); +#if 0 + fd_recalibrate(drv); + fdctrl_reset_fifo(drv->fdctrl); + fdctrl_raise_irq(drv->fdctrl, 0x20); +#endif +} + +fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, + uint32_t io_base, + BlockDriverState **fds) +{ + fdctrl_t *fdctrl; +// int io_mem; + int i; + + FLOPPY_DPRINTF("init controller\n"); + fdctrl = qemu_mallocz(sizeof(fdctrl_t)); + if (!fdctrl) + return NULL; + fdctrl->result_timer = qemu_new_timer(vm_clock, + fdctrl_result_timer, fdctrl); + + fdctrl->version = 0x90; /* Intel 82078 controller */ + fdctrl->irq_lvl = irq_lvl; + fdctrl->dma_chann = dma_chann; + fdctrl->io_base = io_base; + fdctrl->config = 0x60; /* Implicit seek, polling & FIFO enabled */ + if (fdctrl->dma_chann != -1) { + fdctrl->dma_en = 1; + DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl); + } else { + fdctrl->dma_en = 0; + } + for (i = 0; i < 2; i++) { + fd_init(&fdctrl->drives[i], fds[i]); + if (fds[i]) { + bdrv_set_change_cb(fds[i], + &fd_change_cb, &fdctrl->drives[i]); + } + } + fdctrl_reset(fdctrl, 0); + fdctrl->state = FD_CTRL_ACTIVE; + if (mem_mapped) { + FLOPPY_ERROR("memory mapped floppy not supported by now !\n"); +#if 0 + io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write); + cpu_register_physical_memory(base, 0x08, io_mem); +#endif + } else { + register_ioport_read(io_base + 0x01, 5, 1, &fdctrl_read, fdctrl); + register_ioport_read(io_base + 0x07, 1, 1, &fdctrl_read, fdctrl); + register_ioport_write(io_base + 0x01, 5, 1, &fdctrl_write, fdctrl); + register_ioport_write(io_base + 0x07, 1, 1, &fdctrl_write, fdctrl); + } + for (i = 0; i < 2; i++) { + fd_revalidate(&fdctrl->drives[i]); + } + + return fdctrl; +} + +/* XXX: may change if moved to bdrv */ +int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num) +{ + return fdctrl->drives[drive_num].drive; +} + +/* Change IRQ state */ +static void fdctrl_reset_irq (fdctrl_t *fdctrl) +{ + FLOPPY_DPRINTF("Reset interrupt\n"); + pic_set_irq(fdctrl->irq_lvl, 0); + fdctrl->state &= ~FD_CTRL_INTR; +} + +static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status) +{ + if (~(fdctrl->state & FD_CTRL_INTR)) { + pic_set_irq(fdctrl->irq_lvl, 1); + fdctrl->state |= FD_CTRL_INTR; + } + FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", status); + fdctrl->int_status = status; +} + +/* Reset controller */ +static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq) +{ + int i; + + FLOPPY_DPRINTF("reset controller\n"); + fdctrl_reset_irq(fdctrl); + /* Initialise controller */ + fdctrl->cur_drv = 0; + /* FIFO state */ + fdctrl->data_pos = 0; + fdctrl->data_len = 0; + fdctrl->data_state = FD_STATE_CMD; + fdctrl->data_dir = FD_DIR_WRITE; + for (i = 0; i < MAX_FD; i++) + fd_reset(&fdctrl->drives[i]); + fdctrl_reset_fifo(fdctrl); + if (do_irq) + fdctrl_raise_irq(fdctrl, 0xc0); +} + +static inline fdrive_t *drv0 (fdctrl_t *fdctrl) +{ + return &fdctrl->drives[fdctrl->bootsel]; +} + +static inline fdrive_t *drv1 (fdctrl_t *fdctrl) +{ + return &fdctrl->drives[1 - fdctrl->bootsel]; +} + +static fdrive_t *get_cur_drv (fdctrl_t *fdctrl) +{ + return fdctrl->cur_drv == 0 ? drv0(fdctrl) : drv1(fdctrl); +} + +/* Status B register : 0x01 (read-only) */ +static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl) +{ + FLOPPY_DPRINTF("status register: 0x00\n"); + return 0; +} + +/* Digital output register : 0x02 */ +static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl) +{ + uint32_t retval = 0; + + /* Drive motors state indicators */ + if (drv0(fdctrl)->drflags & FDRIVE_MOTOR_ON) + retval |= 1 << 5; + if (drv1(fdctrl)->drflags & FDRIVE_MOTOR_ON) + retval |= 1 << 4; + /* DMA enable */ + retval |= fdctrl->dma_en << 3; + /* Reset indicator */ + retval |= (fdctrl->state & FD_CTRL_RESET) == 0 ? 0x04 : 0; + /* Selected drive */ + retval |= fdctrl->cur_drv; + FLOPPY_DPRINTF("digital output register: 0x%02x\n", retval); + + return retval; +} + +static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value) +{ + /* Reset mode */ + if (fdctrl->state & FD_CTRL_RESET) { + if (!(value & 0x04)) { + FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); + return; + } + } + FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value); + /* Drive motors state indicators */ + if (value & 0x20) + fd_start(drv1(fdctrl)); + else + fd_stop(drv1(fdctrl)); + if (value & 0x10) + fd_start(drv0(fdctrl)); + else + fd_stop(drv0(fdctrl)); + /* DMA enable */ +#if 0 + if (fdctrl->dma_chann != -1) + fdctrl->dma_en = 1 - ((value >> 3) & 1); +#endif + /* Reset */ + if (!(value & 0x04)) { + if (!(fdctrl->state & FD_CTRL_RESET)) { + FLOPPY_DPRINTF("controller enter RESET state\n"); + fdctrl->state |= FD_CTRL_RESET; + } + } else { + if (fdctrl->state & FD_CTRL_RESET) { + FLOPPY_DPRINTF("controller out of RESET state\n"); + fdctrl_reset(fdctrl, 1); + fdctrl->state &= ~(FD_CTRL_RESET | FD_CTRL_SLEEP); + } + } + /* Selected drive */ + fdctrl->cur_drv = value & 1; +} + +/* Tape drive register : 0x03 */ +static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl) +{ + uint32_t retval = 0; + + /* Disk boot selection indicator */ + retval |= fdctrl->bootsel << 2; + /* Tape indicators: never allowed */ + FLOPPY_DPRINTF("tape drive register: 0x%02x\n", retval); + + return retval; +} + +static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value) +{ + /* Reset mode */ + if (fdctrl->state & FD_CTRL_RESET) { + FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); + return; + } + FLOPPY_DPRINTF("tape drive register set to 0x%02x\n", value); + /* Disk boot selection indicator */ + fdctrl->bootsel = (value >> 2) & 1; + /* Tape indicators: never allow */ +} + +/* Main status register : 0x04 (read) */ +static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl) +{ + uint32_t retval = 0; + + fdctrl->state &= ~(FD_CTRL_SLEEP | FD_CTRL_RESET); + if (!(fdctrl->state & FD_CTRL_BUSY)) { + /* Data transfer allowed */ + retval |= 0x80; + /* Data transfer direction indicator */ + if (fdctrl->data_dir == FD_DIR_READ) + retval |= 0x40; + } + /* Should handle 0x20 for SPECIFY command */ + /* Command busy indicator */ + if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA || + FD_STATE(fdctrl->data_state) == FD_STATE_STATUS) + retval |= 0x10; + FLOPPY_DPRINTF("main status register: 0x%02x\n", retval); + + return retval; +} + +/* Data select rate register : 0x04 (write) */ +static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value) +{ + /* Reset mode */ + if (fdctrl->state & FD_CTRL_RESET) { + FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); + return; + } + FLOPPY_DPRINTF("select rate register set to 0x%02x\n", value); + /* Reset: autoclear */ + if (value & 0x80) { + fdctrl->state |= FD_CTRL_RESET; + fdctrl_reset(fdctrl, 1); + fdctrl->state &= ~FD_CTRL_RESET; + } + if (value & 0x40) { + fdctrl->state |= FD_CTRL_SLEEP; + fdctrl_reset(fdctrl, 1); + } +// fdctrl.precomp = (value >> 2) & 0x07; +} + +/* Digital input register : 0x07 (read-only) */ +static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl) +{ + uint32_t retval = 0; + + if (drv0(fdctrl)->drflags & FDRIVE_REVALIDATE || + drv1(fdctrl)->drflags & FDRIVE_REVALIDATE) + retval |= 0x80; + if (retval != 0) + FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval); + drv0(fdctrl)->drflags &= ~FDRIVE_REVALIDATE; + drv1(fdctrl)->drflags &= ~FDRIVE_REVALIDATE; + + return retval; +} + +/* FIFO state control */ +static void fdctrl_reset_fifo (fdctrl_t *fdctrl) +{ + fdctrl->data_dir = FD_DIR_WRITE; + fdctrl->data_pos = 0; + FD_SET_STATE(fdctrl->data_state, FD_STATE_CMD); +} + +/* Set FIFO status for the host to read */ +static void fdctrl_set_fifo (fdctrl_t *fdctrl, int fifo_len, int do_irq) +{ + fdctrl->data_dir = FD_DIR_READ; + fdctrl->data_len = fifo_len; + fdctrl->data_pos = 0; + FD_SET_STATE(fdctrl->data_state, FD_STATE_STATUS); + if (do_irq) + fdctrl_raise_irq(fdctrl, 0x00); +} + +/* Set an error: unimplemented/unknown command */ +static void fdctrl_unimplemented (fdctrl_t *fdctrl) +{ +#if 0 + fdrive_t *cur_drv; + + cur_drv = get_cur_drv(fdctrl); + fdctrl->fifo[0] = 0x60 | (cur_drv->head << 2) | fdctrl->cur_drv; + fdctrl->fifo[1] = 0x00; + fdctrl->fifo[2] = 0x00; + fdctrl_set_fifo(fdctrl, 3, 1); +#else + // fdctrl_reset_fifo(fdctrl); + fdctrl->fifo[0] = 0x80; + fdctrl_set_fifo(fdctrl, 1, 0); +#endif +} + +/* Callback for transfer end (stop or abort) */ +static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0, + uint8_t status1, uint8_t status2) +{ + fdrive_t *cur_drv; + + cur_drv = get_cur_drv(fdctrl); + FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n", + status0, status1, status2, + status0 | (cur_drv->head << 2) | fdctrl->cur_drv); + fdctrl->fifo[0] = status0 | (cur_drv->head << 2) | fdctrl->cur_drv; + fdctrl->fifo[1] = status1; + fdctrl->fifo[2] = status2; + fdctrl->fifo[3] = cur_drv->track; + fdctrl->fifo[4] = cur_drv->head; + fdctrl->fifo[5] = cur_drv->sect; + fdctrl->fifo[6] = FD_SECTOR_SC; + fdctrl->data_dir = FD_DIR_READ; + if (fdctrl->state & FD_CTRL_BUSY) { + DMA_release_DREQ(fdctrl->dma_chann); + fdctrl->state &= ~FD_CTRL_BUSY; + } + fdctrl_set_fifo(fdctrl, 7, 1); +} + +/* Prepare a data transfer (either DMA or FIFO) */ +static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction) +{ + fdrive_t *cur_drv; + uint8_t kh, kt, ks; + int did_seek; + + fdctrl->cur_drv = fdctrl->fifo[1] & 1; + cur_drv = get_cur_drv(fdctrl); + kt = fdctrl->fifo[2]; + kh = fdctrl->fifo[3]; + ks = fdctrl->fifo[4]; + FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n", + fdctrl->cur_drv, kh, kt, ks, + _fd_sector(kh, kt, ks, cur_drv->last_sect)); + did_seek = 0; + switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & 0x40)) { + case 2: + /* sect too big */ + fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00); + fdctrl->fifo[3] = kt; + fdctrl->fifo[4] = kh; + fdctrl->fifo[5] = ks; + return; + case 3: + /* track too big */ + fdctrl_stop_transfer(fdctrl, 0x40, 0x80, 0x00); + fdctrl->fifo[3] = kt; + fdctrl->fifo[4] = kh; + fdctrl->fifo[5] = ks; + return; + case 4: + /* No seek enabled */ + fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00); + fdctrl->fifo[3] = kt; + fdctrl->fifo[4] = kh; + fdctrl->fifo[5] = ks; + return; + case 1: + did_seek = 1; + break; + default: + break; + } + /* Set the FIFO state */ + fdctrl->data_dir = direction; + fdctrl->data_pos = 0; + FD_SET_STATE(fdctrl->data_state, FD_STATE_DATA); /* FIFO ready for data */ + if (fdctrl->fifo[0] & 0x80) + fdctrl->data_state |= FD_STATE_MULTI; + else + fdctrl->data_state &= ~FD_STATE_MULTI; + if (did_seek) + fdctrl->data_state |= FD_STATE_SEEK; + else + fdctrl->data_state &= ~FD_STATE_SEEK; + if (fdctrl->fifo[5] == 00) { + fdctrl->data_len = fdctrl->fifo[8]; + } else { + int tmp; + fdctrl->data_len = 128 << fdctrl->fifo[5]; + tmp = (cur_drv->last_sect - ks + 1); + if (fdctrl->fifo[0] & 0x80) + tmp += cur_drv->last_sect; + fdctrl->data_len *= tmp; + } + fdctrl->eot = fdctrl->fifo[6]; + if (fdctrl->dma_en) { + int dma_mode; + /* DMA transfer are enabled. Check if DMA channel is well programmed */ + dma_mode = DMA_get_channel_mode(fdctrl->dma_chann); + dma_mode = (dma_mode >> 2) & 3; + FLOPPY_DPRINTF("dma_mode=%d direction=%d (%d - %d)\n", + dma_mode, direction, + (128 << fdctrl->fifo[5]) * + (cur_drv->last_sect - ks + 1), fdctrl->data_len); + if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL || + direction == FD_DIR_SCANH) && dma_mode == 0) || + (direction == FD_DIR_WRITE && dma_mode == 2) || + (direction == FD_DIR_READ && dma_mode == 1)) { + /* No access is allowed until DMA transfer has completed */ + fdctrl->state |= FD_CTRL_BUSY; + /* Now, we just have to wait for the DMA controller to + * recall us... + */ + DMA_hold_DREQ(fdctrl->dma_chann); + DMA_schedule(fdctrl->dma_chann); + return; + } else { + FLOPPY_ERROR("dma_mode=%d direction=%d\n", dma_mode, direction); + } + } + FLOPPY_DPRINTF("start non-DMA transfer\n"); + /* IO based transfer: calculate len */ + fdctrl_raise_irq(fdctrl, 0x00); + + return; +} + +/* Prepare a transfer of deleted data */ +static void fdctrl_start_transfer_del (fdctrl_t *fdctrl, int direction) +{ + /* We don't handle deleted data, + * so we don't return *ANYTHING* + */ + fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00); +} + +/* handlers for DMA transfers */ +static int fdctrl_transfer_handler (void *opaque, int nchan, + int dma_pos, int dma_len) +{ + fdctrl_t *fdctrl; + fdrive_t *cur_drv; + int len, start_pos, rel_pos; + uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00; + + fdctrl = opaque; + if (!(fdctrl->state & FD_CTRL_BUSY)) { + FLOPPY_DPRINTF("Not in DMA transfer mode !\n"); + return 0; + } + cur_drv = get_cur_drv(fdctrl); + if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL || + fdctrl->data_dir == FD_DIR_SCANH) + status2 = 0x04; + if (dma_len > fdctrl->data_len) + dma_len = fdctrl->data_len; + if (cur_drv->bs == NULL) { + if (fdctrl->data_dir == FD_DIR_WRITE) + fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00); + else + fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00); + len = 0; + goto transfer_error; + } + rel_pos = fdctrl->data_pos % FD_SECTOR_LEN; + for (start_pos = fdctrl->data_pos; fdctrl->data_pos < dma_len;) { + len = dma_len - fdctrl->data_pos; + if (len + rel_pos > FD_SECTOR_LEN) + len = FD_SECTOR_LEN - rel_pos; + FLOPPY_DPRINTF("copy %d bytes (%d %d %d) %d pos %d %02x %02x " + "(%d-0x%08x 0x%08x)\n", len, size, fdctrl->data_pos, + fdctrl->data_len, fdctrl->cur_drv, cur_drv->head, + cur_drv->track, cur_drv->sect, fd_sector(cur_drv), + fd_sector(cur_drv) * 512, addr); + if (fdctrl->data_dir != FD_DIR_WRITE || + len < FD_SECTOR_LEN || rel_pos != 0) { + /* READ & SCAN commands and realign to a sector for WRITE */ + if (bdrv_read(cur_drv->bs, fd_sector(cur_drv), + fdctrl->fifo, 1) < 0) { + FLOPPY_DPRINTF("Floppy: error getting sector %d\n", + fd_sector(cur_drv)); + /* Sure, image size is too small... */ + memset(fdctrl->fifo, 0, FD_SECTOR_LEN); + } + } + switch (fdctrl->data_dir) { + case FD_DIR_READ: + /* READ commands */ + DMA_write_memory (nchan, fdctrl->fifo + rel_pos, + fdctrl->data_pos, len); +/* cpu_physical_memory_write(addr + fdctrl->data_pos, */ +/* fdctrl->fifo + rel_pos, len); */ + break; + case FD_DIR_WRITE: + /* WRITE commands */ + DMA_read_memory (nchan, fdctrl->fifo + rel_pos, + fdctrl->data_pos, len); +/* cpu_physical_memory_read(addr + fdctrl->data_pos, */ +/* fdctrl->fifo + rel_pos, len); */ + if (bdrv_write(cur_drv->bs, fd_sector(cur_drv), + fdctrl->fifo, 1) < 0) { + FLOPPY_ERROR("writting sector %d\n", fd_sector(cur_drv)); + fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00); + goto transfer_error; + } + break; + default: + /* SCAN commands */ + { + uint8_t tmpbuf[FD_SECTOR_LEN]; + int ret; + DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len); +/* cpu_physical_memory_read(addr + fdctrl->data_pos, */ +/* tmpbuf, len); */ + ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len); + if (ret == 0) { + status2 = 0x08; + goto end_transfer; + } + if ((ret < 0 && fdctrl->data_dir == FD_DIR_SCANL) || + (ret > 0 && fdctrl->data_dir == FD_DIR_SCANH)) { + status2 = 0x00; + goto end_transfer; + } + } + break; + } + fdctrl->data_pos += len; + rel_pos = fdctrl->data_pos % FD_SECTOR_LEN; + if (rel_pos == 0) { + /* Seek to next sector */ + FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d) (%d)\n", + cur_drv->head, cur_drv->track, cur_drv->sect, + fd_sector(cur_drv), + fdctrl->data_pos - size); + /* XXX: cur_drv->sect >= cur_drv->last_sect should be an + error in fact */ + if (cur_drv->sect >= cur_drv->last_sect || + cur_drv->sect == fdctrl->eot) { + cur_drv->sect = 1; + if (FD_MULTI_TRACK(fdctrl->data_state)) { + if (cur_drv->head == 0 && + (cur_drv->flags & FDISK_DBL_SIDES) != 0) { + cur_drv->head = 1; + } else { + cur_drv->head = 0; + cur_drv->track++; + if ((cur_drv->flags & FDISK_DBL_SIDES) == 0) + break; + } + } else { + cur_drv->track++; + break; + } + FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n", + cur_drv->head, cur_drv->track, + cur_drv->sect, fd_sector(cur_drv)); + } else { + cur_drv->sect++; + } + } + } +end_transfer: + len = fdctrl->data_pos - start_pos; + FLOPPY_DPRINTF("end transfer %d %d %d\n", + fdctrl->data_pos, len, fdctrl->data_len); + if (fdctrl->data_dir == FD_DIR_SCANE || + fdctrl->data_dir == FD_DIR_SCANL || + fdctrl->data_dir == FD_DIR_SCANH) + status2 = 0x08; + if (FD_DID_SEEK(fdctrl->data_state)) + status0 |= 0x20; + fdctrl->data_len -= len; + // if (fdctrl->data_len == 0) + fdctrl_stop_transfer(fdctrl, status0, status1, status2); +transfer_error: + + return len; +} + +/* Data register : 0x05 */ +static uint32_t fdctrl_read_data (fdctrl_t *fdctrl) +{ + fdrive_t *cur_drv; + uint32_t retval = 0; + int pos, len; + + cur_drv = get_cur_drv(fdctrl); + fdctrl->state &= ~FD_CTRL_SLEEP; + if (FD_STATE(fdctrl->data_state) == FD_STATE_CMD) { + FLOPPY_ERROR("can't read data in CMD state\n"); + return 0; + } + pos = fdctrl->data_pos; + if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) { + pos %= FD_SECTOR_LEN; + if (pos == 0) { + len = fdctrl->data_len - fdctrl->data_pos; + if (len > FD_SECTOR_LEN) + len = FD_SECTOR_LEN; + bdrv_read(cur_drv->bs, fd_sector(cur_drv), + fdctrl->fifo, len); + } + } + retval = fdctrl->fifo[pos]; + if (++fdctrl->data_pos == fdctrl->data_len) { + fdctrl->data_pos = 0; + /* Switch from transfer mode to status mode + * then from status mode to command mode + */ + if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) { + fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00); + } else { + fdctrl_reset_fifo(fdctrl); + fdctrl_reset_irq(fdctrl); + } + } + FLOPPY_DPRINTF("data register: 0x%02x\n", retval); + + return retval; +} + +static void fdctrl_format_sector (fdctrl_t *fdctrl) +{ + fdrive_t *cur_drv; + uint8_t kh, kt, ks; + int did_seek; + + fdctrl->cur_drv = fdctrl->fifo[1] & 1; + cur_drv = get_cur_drv(fdctrl); + kt = fdctrl->fifo[6]; + kh = fdctrl->fifo[7]; + ks = fdctrl->fifo[8]; + FLOPPY_DPRINTF("format sector at %d %d %02x %02x (%d)\n", + fdctrl->cur_drv, kh, kt, ks, + _fd_sector(kh, kt, ks, cur_drv->last_sect)); + did_seek = 0; + switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & 0x40)) { + case 2: + /* sect too big */ + fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00); + fdctrl->fifo[3] = kt; + fdctrl->fifo[4] = kh; + fdctrl->fifo[5] = ks; + return; + case 3: + /* track too big */ + fdctrl_stop_transfer(fdctrl, 0x40, 0x80, 0x00); + fdctrl->fifo[3] = kt; + fdctrl->fifo[4] = kh; + fdctrl->fifo[5] = ks; + return; + case 4: + /* No seek enabled */ + fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00); + fdctrl->fifo[3] = kt; + fdctrl->fifo[4] = kh; + fdctrl->fifo[5] = ks; + return; + case 1: + did_seek = 1; + fdctrl->data_state |= FD_STATE_SEEK; + break; + default: + break; + } + memset(fdctrl->fifo, 0, FD_SECTOR_LEN); + if (cur_drv->bs == NULL || + bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) { + FLOPPY_ERROR("formating sector %d\n", fd_sector(cur_drv)); + fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00); + } else { + if (cur_drv->sect == cur_drv->last_sect) { + fdctrl->data_state &= ~FD_STATE_FORMAT; + /* Last sector done */ + if (FD_DID_SEEK(fdctrl->data_state)) + fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00); + else + fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); + } else { + /* More to do */ + fdctrl->data_pos = 0; + fdctrl->data_len = 4; + } + } +} + +static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value) +{ + fdrive_t *cur_drv; + + cur_drv = get_cur_drv(fdctrl); + /* Reset mode */ + if (fdctrl->state & FD_CTRL_RESET) { + FLOPPY_DPRINTF("Floppy controller in RESET state !\n"); + return; + } + fdctrl->state &= ~FD_CTRL_SLEEP; + if (FD_STATE(fdctrl->data_state) == FD_STATE_STATUS) { + FLOPPY_ERROR("can't write data in status mode\n"); + return; + } + /* Is it write command time ? */ + if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) { + /* FIFO data write */ + fdctrl->fifo[fdctrl->data_pos++] = value; + if (fdctrl->data_pos % FD_SECTOR_LEN == (FD_SECTOR_LEN - 1) || + fdctrl->data_pos == fdctrl->data_len) { + bdrv_write(cur_drv->bs, fd_sector(cur_drv), + fdctrl->fifo, FD_SECTOR_LEN); + } + /* Switch from transfer mode to status mode + * then from status mode to command mode + */ + if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) + fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00); + return; + } + if (fdctrl->data_pos == 0) { + /* Command */ + switch (value & 0x5F) { + case 0x46: + /* READ variants */ + FLOPPY_DPRINTF("READ command\n"); + /* 8 parameters cmd */ + fdctrl->data_len = 9; + goto enqueue; + case 0x4C: + /* READ_DELETED variants */ + FLOPPY_DPRINTF("READ_DELETED command\n"); + /* 8 parameters cmd */ + fdctrl->data_len = 9; + goto enqueue; + case 0x50: + /* SCAN_EQUAL variants */ + FLOPPY_DPRINTF("SCAN_EQUAL command\n"); + /* 8 parameters cmd */ + fdctrl->data_len = 9; + goto enqueue; + case 0x56: + /* VERIFY variants */ + FLOPPY_DPRINTF("VERIFY command\n"); + /* 8 parameters cmd */ + fdctrl->data_len = 9; + goto enqueue; + case 0x59: + /* SCAN_LOW_OR_EQUAL variants */ + FLOPPY_DPRINTF("SCAN_LOW_OR_EQUAL command\n"); + /* 8 parameters cmd */ + fdctrl->data_len = 9; + goto enqueue; + case 0x5D: + /* SCAN_HIGH_OR_EQUAL variants */ + FLOPPY_DPRINTF("SCAN_HIGH_OR_EQUAL command\n"); + /* 8 parameters cmd */ + fdctrl->data_len = 9; + goto enqueue; + default: + break; + } + switch (value & 0x7F) { + case 0x45: + /* WRITE variants */ + FLOPPY_DPRINTF("WRITE command\n"); + /* 8 parameters cmd */ + fdctrl->data_len = 9; + goto enqueue; + case 0x49: + /* WRITE_DELETED variants */ + FLOPPY_DPRINTF("WRITE_DELETED command\n"); + /* 8 parameters cmd */ + fdctrl->data_len = 9; + goto enqueue; + default: + break; + } + switch (value) { + case 0x03: + /* SPECIFY */ + FLOPPY_DPRINTF("SPECIFY command\n"); + /* 1 parameter cmd */ + fdctrl->data_len = 3; + goto enqueue; + case 0x04: + /* SENSE_DRIVE_STATUS */ + FLOPPY_DPRINTF("SENSE_DRIVE_STATUS command\n"); + /* 1 parameter cmd */ + fdctrl->data_len = 2; + goto enqueue; + case 0x07: + /* RECALIBRATE */ + FLOPPY_DPRINTF("RECALIBRATE command\n"); + /* 1 parameter cmd */ + fdctrl->data_len = 2; + goto enqueue; + case 0x08: + /* SENSE_INTERRUPT_STATUS */ + FLOPPY_DPRINTF("SENSE_INTERRUPT_STATUS command (%02x)\n", + fdctrl->int_status); + /* No parameters cmd: returns status if no interrupt */ +#if 0 + fdctrl->fifo[0] = + fdctrl->int_status | (cur_drv->head << 2) | fdctrl->cur_drv; +#else + /* XXX: int_status handling is broken for read/write + commands, so we do this hack. It should be suppressed + ASAP */ + fdctrl->fifo[0] = + 0x20 | (cur_drv->head << 2) | fdctrl->cur_drv; +#endif + fdctrl->fifo[1] = cur_drv->track; + fdctrl_set_fifo(fdctrl, 2, 0); + fdctrl_reset_irq(fdctrl); + fdctrl->int_status = 0xC0; + return; + case 0x0E: + /* DUMPREG */ + FLOPPY_DPRINTF("DUMPREG command\n"); + /* Drives position */ + fdctrl->fifo[0] = drv0(fdctrl)->track; + fdctrl->fifo[1] = drv1(fdctrl)->track; + fdctrl->fifo[2] = 0; + fdctrl->fifo[3] = 0; + /* timers */ + fdctrl->fifo[4] = fdctrl->timer0; + fdctrl->fifo[5] = (fdctrl->timer1 << 1) | fdctrl->dma_en; + fdctrl->fifo[6] = cur_drv->last_sect; + fdctrl->fifo[7] = (fdctrl->lock << 7) | + (cur_drv->perpendicular << 2); + fdctrl->fifo[8] = fdctrl->config; + fdctrl->fifo[9] = fdctrl->precomp_trk; + fdctrl_set_fifo(fdctrl, 10, 0); + return; + case 0x0F: + /* SEEK */ + FLOPPY_DPRINTF("SEEK command\n"); + /* 2 parameters cmd */ + fdctrl->data_len = 3; + goto enqueue; + case 0x10: + /* VERSION */ + FLOPPY_DPRINTF("VERSION command\n"); + /* No parameters cmd */ + /* Controller's version */ + fdctrl->fifo[0] = fdctrl->version; + fdctrl_set_fifo(fdctrl, 1, 1); + return; + case 0x12: + /* PERPENDICULAR_MODE */ + FLOPPY_DPRINTF("PERPENDICULAR_MODE command\n"); + /* 1 parameter cmd */ + fdctrl->data_len = 2; + goto enqueue; + case 0x13: + /* CONFIGURE */ + FLOPPY_DPRINTF("CONFIGURE command\n"); + /* 3 parameters cmd */ + fdctrl->data_len = 4; + goto enqueue; + case 0x14: + /* UNLOCK */ + FLOPPY_DPRINTF("UNLOCK command\n"); + /* No parameters cmd */ + fdctrl->lock = 0; + fdctrl->fifo[0] = 0; + fdctrl_set_fifo(fdctrl, 1, 0); + return; + case 0x17: + /* POWERDOWN_MODE */ + FLOPPY_DPRINTF("POWERDOWN_MODE command\n"); + /* 2 parameters cmd */ + fdctrl->data_len = 3; + goto enqueue; + case 0x18: + /* PART_ID */ + FLOPPY_DPRINTF("PART_ID command\n"); + /* No parameters cmd */ + fdctrl->fifo[0] = 0x41; /* Stepping 1 */ + fdctrl_set_fifo(fdctrl, 1, 0); + return; + case 0x2C: + /* SAVE */ + FLOPPY_DPRINTF("SAVE command\n"); + /* No parameters cmd */ + fdctrl->fifo[0] = 0; + fdctrl->fifo[1] = 0; + /* Drives position */ + fdctrl->fifo[2] = drv0(fdctrl)->track; + fdctrl->fifo[3] = drv1(fdctrl)->track; + fdctrl->fifo[4] = 0; + fdctrl->fifo[5] = 0; + /* timers */ + fdctrl->fifo[6] = fdctrl->timer0; + fdctrl->fifo[7] = fdctrl->timer1; + fdctrl->fifo[8] = cur_drv->last_sect; + fdctrl->fifo[9] = (fdctrl->lock << 7) | + (cur_drv->perpendicular << 2); + fdctrl->fifo[10] = fdctrl->config; + fdctrl->fifo[11] = fdctrl->precomp_trk; + fdctrl->fifo[12] = fdctrl->pwrd; + fdctrl->fifo[13] = 0; + fdctrl->fifo[14] = 0; + fdctrl_set_fifo(fdctrl, 15, 1); + return; + case 0x33: + /* OPTION */ + FLOPPY_DPRINTF("OPTION command\n"); + /* 1 parameter cmd */ + fdctrl->data_len = 2; + goto enqueue; + case 0x42: + /* READ_TRACK */ + FLOPPY_DPRINTF("READ_TRACK command\n"); + /* 8 parameters cmd */ + fdctrl->data_len = 9; + goto enqueue; + case 0x4A: + /* READ_ID */ + FLOPPY_DPRINTF("READ_ID command\n"); + /* 1 parameter cmd */ + fdctrl->data_len = 2; + goto enqueue; + case 0x4C: + /* RESTORE */ + FLOPPY_DPRINTF("RESTORE command\n"); + /* 17 parameters cmd */ + fdctrl->data_len = 18; + goto enqueue; + case 0x4D: + /* FORMAT_TRACK */ + FLOPPY_DPRINTF("FORMAT_TRACK command\n"); + /* 5 parameters cmd */ + fdctrl->data_len = 6; + goto enqueue; + case 0x8E: + /* DRIVE_SPECIFICATION_COMMAND */ + FLOPPY_DPRINTF("DRIVE_SPECIFICATION_COMMAND command\n"); + /* 5 parameters cmd */ + fdctrl->data_len = 6; + goto enqueue; + case 0x8F: + /* RELATIVE_SEEK_OUT */ + FLOPPY_DPRINTF("RELATIVE_SEEK_OUT command\n"); + /* 2 parameters cmd */ + fdctrl->data_len = 3; + goto enqueue; + case 0x94: + /* LOCK */ + FLOPPY_DPRINTF("LOCK command\n"); + /* No parameters cmd */ + fdctrl->lock = 1; + fdctrl->fifo[0] = 0x10; + fdctrl_set_fifo(fdctrl, 1, 1); + return; + case 0xCD: + /* FORMAT_AND_WRITE */ + FLOPPY_DPRINTF("FORMAT_AND_WRITE command\n"); + /* 10 parameters cmd */ + fdctrl->data_len = 11; + goto enqueue; + case 0xCF: + /* RELATIVE_SEEK_IN */ + FLOPPY_DPRINTF("RELATIVE_SEEK_IN command\n"); + /* 2 parameters cmd */ + fdctrl->data_len = 3; + goto enqueue; + default: + /* Unknown command */ + FLOPPY_ERROR("unknown command: 0x%02x\n", value); + fdctrl_unimplemented(fdctrl); + return; + } + } +enqueue: + FLOPPY_DPRINTF("%s: %02x\n", __func__, value); + fdctrl->fifo[fdctrl->data_pos] = value; + if (++fdctrl->data_pos == fdctrl->data_len) { + /* We now have all parameters + * and will be able to treat the command + */ + if (fdctrl->data_state & FD_STATE_FORMAT) { + fdctrl_format_sector(fdctrl); + return; + } + switch (fdctrl->fifo[0] & 0x1F) { + case 0x06: + { + /* READ variants */ + FLOPPY_DPRINTF("treat READ command\n"); + fdctrl_start_transfer(fdctrl, FD_DIR_READ); + return; + } + case 0x0C: + /* READ_DELETED variants */ +// FLOPPY_DPRINTF("treat READ_DELETED command\n"); + FLOPPY_ERROR("treat READ_DELETED command\n"); + fdctrl_start_transfer_del(fdctrl, FD_DIR_READ); + return; + case 0x16: + /* VERIFY variants */ +// FLOPPY_DPRINTF("treat VERIFY command\n"); + FLOPPY_ERROR("treat VERIFY command\n"); + fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00); + return; + case 0x10: + /* SCAN_EQUAL variants */ +// FLOPPY_DPRINTF("treat SCAN_EQUAL command\n"); + FLOPPY_ERROR("treat SCAN_EQUAL command\n"); + fdctrl_start_transfer(fdctrl, FD_DIR_SCANE); + return; + case 0x19: + /* SCAN_LOW_OR_EQUAL variants */ +// FLOPPY_DPRINTF("treat SCAN_LOW_OR_EQUAL command\n"); + FLOPPY_ERROR("treat SCAN_LOW_OR_EQUAL command\n"); + fdctrl_start_transfer(fdctrl, FD_DIR_SCANL); + return; + case 0x1D: + /* SCAN_HIGH_OR_EQUAL variants */ +// FLOPPY_DPRINTF("treat SCAN_HIGH_OR_EQUAL command\n"); + FLOPPY_ERROR("treat SCAN_HIGH_OR_EQUAL command\n"); + fdctrl_start_transfer(fdctrl, FD_DIR_SCANH); + return; + default: + break; + } + switch (fdctrl->fifo[0] & 0x3F) { + case 0x05: + /* WRITE variants */ + FLOPPY_DPRINTF("treat WRITE command (%02x)\n", fdctrl->fifo[0]); + fdctrl_start_transfer(fdctrl, FD_DIR_WRITE); + return; + case 0x09: + /* WRITE_DELETED variants */ +// FLOPPY_DPRINTF("treat WRITE_DELETED command\n"); + FLOPPY_ERROR("treat WRITE_DELETED command\n"); + fdctrl_start_transfer_del(fdctrl, FD_DIR_WRITE); + return; + default: + break; + } + switch (fdctrl->fifo[0]) { + case 0x03: + /* SPECIFY */ + FLOPPY_DPRINTF("treat SPECIFY command\n"); + fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF; + fdctrl->timer1 = fdctrl->fifo[2] >> 1; + fdctrl->dma_en = 1 - (fdctrl->fifo[2] & 1) ; + /* No result back */ + fdctrl_reset_fifo(fdctrl); + break; + case 0x04: + /* SENSE_DRIVE_STATUS */ + FLOPPY_DPRINTF("treat SENSE_DRIVE_STATUS command\n"); + fdctrl->cur_drv = fdctrl->fifo[1] & 1; + cur_drv = get_cur_drv(fdctrl); + cur_drv->head = (fdctrl->fifo[1] >> 2) & 1; + /* 1 Byte status back */ + fdctrl->fifo[0] = (cur_drv->ro << 6) | + (cur_drv->track == 0 ? 0x10 : 0x00) | + (cur_drv->head << 2) | + fdctrl->cur_drv | + 0x28; + fdctrl_set_fifo(fdctrl, 1, 0); + break; + case 0x07: + /* RECALIBRATE */ + FLOPPY_DPRINTF("treat RECALIBRATE command\n"); + fdctrl->cur_drv = fdctrl->fifo[1] & 1; + cur_drv = get_cur_drv(fdctrl); + fd_recalibrate(cur_drv); + fdctrl_reset_fifo(fdctrl); + /* Raise Interrupt */ + fdctrl_raise_irq(fdctrl, 0x20); + break; + case 0x0F: + /* SEEK */ + FLOPPY_DPRINTF("treat SEEK command\n"); + fdctrl->cur_drv = fdctrl->fifo[1] & 1; + cur_drv = get_cur_drv(fdctrl); + fd_start(cur_drv); + if (fdctrl->fifo[2] <= cur_drv->track) + cur_drv->dir = 1; + else + cur_drv->dir = 0; + fdctrl_reset_fifo(fdctrl); + if (fdctrl->fifo[2] > cur_drv->max_track) { + fdctrl_raise_irq(fdctrl, 0x60); + } else { + cur_drv->track = fdctrl->fifo[2]; + /* Raise Interrupt */ + fdctrl_raise_irq(fdctrl, 0x20); + } + break; + case 0x12: + /* PERPENDICULAR_MODE */ + FLOPPY_DPRINTF("treat PERPENDICULAR_MODE command\n"); + if (fdctrl->fifo[1] & 0x80) + cur_drv->perpendicular = fdctrl->fifo[1] & 0x7; + /* No result back */ + fdctrl_reset_fifo(fdctrl); + break; + case 0x13: + /* CONFIGURE */ + FLOPPY_DPRINTF("treat CONFIGURE command\n"); + fdctrl->config = fdctrl->fifo[2]; + fdctrl->precomp_trk = fdctrl->fifo[3]; + /* No result back */ + fdctrl_reset_fifo(fdctrl); + break; + case 0x17: + /* POWERDOWN_MODE */ + FLOPPY_DPRINTF("treat POWERDOWN_MODE command\n"); + fdctrl->pwrd = fdctrl->fifo[1]; + fdctrl->fifo[0] = fdctrl->fifo[1]; + fdctrl_set_fifo(fdctrl, 1, 1); + break; + case 0x33: + /* OPTION */ + FLOPPY_DPRINTF("treat OPTION command\n"); + /* No result back */ + fdctrl_reset_fifo(fdctrl); + break; + case 0x42: + /* READ_TRACK */ +// FLOPPY_DPRINTF("treat READ_TRACK command\n"); + FLOPPY_ERROR("treat READ_TRACK command\n"); + fdctrl_start_transfer(fdctrl, FD_DIR_READ); + break; + case 0x4A: + /* READ_ID */ + FLOPPY_DPRINTF("treat READ_ID command\n"); + /* XXX: should set main status register to busy */ + cur_drv->head = (fdctrl->fifo[1] >> 2) & 1; + qemu_mod_timer(fdctrl->result_timer, + qemu_get_clock(vm_clock) + (ticks_per_sec / 50)); + break; + case 0x4C: + /* RESTORE */ + FLOPPY_DPRINTF("treat RESTORE command\n"); + /* Drives position */ + drv0(fdctrl)->track = fdctrl->fifo[3]; + drv1(fdctrl)->track = fdctrl->fifo[4]; + /* timers */ + fdctrl->timer0 = fdctrl->fifo[7]; + fdctrl->timer1 = fdctrl->fifo[8]; + cur_drv->last_sect = fdctrl->fifo[9]; + fdctrl->lock = fdctrl->fifo[10] >> 7; + cur_drv->perpendicular = (fdctrl->fifo[10] >> 2) & 0xF; + fdctrl->config = fdctrl->fifo[11]; + fdctrl->precomp_trk = fdctrl->fifo[12]; + fdctrl->pwrd = fdctrl->fifo[13]; + fdctrl_reset_fifo(fdctrl); + break; + case 0x4D: + /* FORMAT_TRACK */ + FLOPPY_DPRINTF("treat FORMAT_TRACK command\n"); + fdctrl->cur_drv = fdctrl->fifo[1] & 1; + cur_drv = get_cur_drv(fdctrl); + fdctrl->data_state |= FD_STATE_FORMAT; + if (fdctrl->fifo[0] & 0x80) + fdctrl->data_state |= FD_STATE_MULTI; + else + fdctrl->data_state &= ~FD_STATE_MULTI; + fdctrl->data_state &= ~FD_STATE_SEEK; + cur_drv->bps = + fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2]; +#if 0 + cur_drv->last_sect = + cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] : + fdctrl->fifo[3] / 2; +#else + cur_drv->last_sect = fdctrl->fifo[3]; +#endif + /* Bochs BIOS is buggy and don't send format informations + * for each sector. So, pretend all's done right now... + */ + fdctrl->data_state &= ~FD_STATE_FORMAT; + fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); + break; + case 0x8E: + /* DRIVE_SPECIFICATION_COMMAND */ + FLOPPY_DPRINTF("treat DRIVE_SPECIFICATION_COMMAND command\n"); + if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) { + /* Command parameters done */ + if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) { + fdctrl->fifo[0] = fdctrl->fifo[1]; + fdctrl->fifo[2] = 0; + fdctrl->fifo[3] = 0; + fdctrl_set_fifo(fdctrl, 4, 1); + } else { + fdctrl_reset_fifo(fdctrl); + } + } else if (fdctrl->data_len > 7) { + /* ERROR */ + fdctrl->fifo[0] = 0x80 | + (cur_drv->head << 2) | fdctrl->cur_drv; + fdctrl_set_fifo(fdctrl, 1, 1); + } + break; + case 0x8F: + /* RELATIVE_SEEK_OUT */ + FLOPPY_DPRINTF("treat RELATIVE_SEEK_OUT command\n"); + fdctrl->cur_drv = fdctrl->fifo[1] & 1; + cur_drv = get_cur_drv(fdctrl); + fd_start(cur_drv); + cur_drv->dir = 0; + if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) { + cur_drv->track = cur_drv->max_track - 1; + } else { + cur_drv->track += fdctrl->fifo[2]; + } + fdctrl_reset_fifo(fdctrl); + fdctrl_raise_irq(fdctrl, 0x20); + break; + case 0xCD: + /* FORMAT_AND_WRITE */ +// FLOPPY_DPRINTF("treat FORMAT_AND_WRITE command\n"); + FLOPPY_ERROR("treat FORMAT_AND_WRITE command\n"); + fdctrl_unimplemented(fdctrl); + break; + case 0xCF: + /* RELATIVE_SEEK_IN */ + FLOPPY_DPRINTF("treat RELATIVE_SEEK_IN command\n"); + fdctrl->cur_drv = fdctrl->fifo[1] & 1; + cur_drv = get_cur_drv(fdctrl); + fd_start(cur_drv); + cur_drv->dir = 1; + if (fdctrl->fifo[2] > cur_drv->track) { + cur_drv->track = 0; + } else { + cur_drv->track -= fdctrl->fifo[2]; + } + fdctrl_reset_fifo(fdctrl); + /* Raise Interrupt */ + fdctrl_raise_irq(fdctrl, 0x20); + break; + } + } +} + +static void fdctrl_result_timer(void *opaque) +{ + fdctrl_t *fdctrl = opaque; + fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00); +} diff --git a/tools/ioemu/hw/fmopl.c b/tools/ioemu/hw/fmopl.c new file mode 100644 index 0000000000..2b0e82b0cc --- /dev/null +++ b/tools/ioemu/hw/fmopl.c @@ -0,0 +1,1390 @@ +/* +** +** File: fmopl.c -- software implementation of FM sound generator +** +** Copyright (C) 1999,2000 Tatsuyuki Satoh , MultiArcadeMachineEmurator development +** +** Version 0.37a +** +*/ + +/* + preliminary : + Problem : + note: +*/ + +/* This version of fmopl.c is a fork of the MAME one, relicensed under the LGPL. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define INLINE __inline +#define HAS_YM3812 1 + +#include +#include +#include +#include +#include +//#include "driver.h" /* use M.A.M.E. */ +#include "fmopl.h" + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +/* -------------------- for debug --------------------- */ +/* #define OPL_OUTPUT_LOG */ +#ifdef OPL_OUTPUT_LOG +static FILE *opl_dbg_fp = NULL; +static FM_OPL *opl_dbg_opl[16]; +static int opl_dbg_maxchip,opl_dbg_chip; +#endif + +/* -------------------- preliminary define section --------------------- */ +/* attack/decay rate time rate */ +#define OPL_ARRATE 141280 /* RATE 4 = 2826.24ms @ 3.6MHz */ +#define OPL_DRRATE 1956000 /* RATE 4 = 39280.64ms @ 3.6MHz */ + +#define DELTAT_MIXING_LEVEL (1) /* DELTA-T ADPCM MIXING LEVEL */ + +#define FREQ_BITS 24 /* frequency turn */ + +/* counter bits = 20 , octerve 7 */ +#define FREQ_RATE (1<<(FREQ_BITS-20)) +#define TL_BITS (FREQ_BITS+2) + +/* final output shift , limit minimum and maximum */ +#define OPL_OUTSB (TL_BITS+3-16) /* OPL output final shift 16bit */ +#define OPL_MAXOUT (0x7fff<=LOG_LEVEL ) logerror x +#define LOG(n,x) + +/* --------------------- subroutines --------------------- */ + +INLINE int Limit( int val, int max, int min ) { + if ( val > max ) + val = max; + else if ( val < min ) + val = min; + + return val; +} + +/* status set and IRQ handling */ +INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag) +{ + /* set status flag */ + OPL->status |= flag; + if(!(OPL->status & 0x80)) + { + if(OPL->status & OPL->statusmask) + { /* IRQ on */ + OPL->status |= 0x80; + /* callback user interrupt handler (IRQ is OFF to ON) */ + if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1); + } + } +} + +/* status reset and IRQ handling */ +INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag) +{ + /* reset status flag */ + OPL->status &=~flag; + if((OPL->status & 0x80)) + { + if (!(OPL->status & OPL->statusmask) ) + { + OPL->status &= 0x7f; + /* callback user interrupt handler (IRQ is ON to OFF) */ + if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0); + } + } +} + +/* IRQ mask set */ +INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag) +{ + OPL->statusmask = flag; + /* IRQ handling check */ + OPL_STATUS_SET(OPL,0); + OPL_STATUS_RESET(OPL,0); +} + +/* ----- key on ----- */ +INLINE void OPL_KEYON(OPL_SLOT *SLOT) +{ + /* sin wave restart */ + SLOT->Cnt = 0; + /* set attack */ + SLOT->evm = ENV_MOD_AR; + SLOT->evs = SLOT->evsa; + SLOT->evc = EG_AST; + SLOT->eve = EG_AED; +} +/* ----- key off ----- */ +INLINE void OPL_KEYOFF(OPL_SLOT *SLOT) +{ + if( SLOT->evm > ENV_MOD_RR) + { + /* set envelope counter from envleope output */ + SLOT->evm = ENV_MOD_RR; + if( !(SLOT->evc&EG_DST) ) + //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<evc = EG_DST; + SLOT->eve = EG_DED; + SLOT->evs = SLOT->evsr; + } +} + +/* ---------- calcrate Envelope Generator & Phase Generator ---------- */ +/* return : envelope output */ +INLINE UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT ) +{ + /* calcrate envelope generator */ + if( (SLOT->evc+=SLOT->evs) >= SLOT->eve ) + { + switch( SLOT->evm ){ + case ENV_MOD_AR: /* ATTACK -> DECAY1 */ + /* next DR */ + SLOT->evm = ENV_MOD_DR; + SLOT->evc = EG_DST; + SLOT->eve = SLOT->SL; + SLOT->evs = SLOT->evsd; + break; + case ENV_MOD_DR: /* DECAY -> SL or RR */ + SLOT->evc = SLOT->SL; + SLOT->eve = EG_DED; + if(SLOT->eg_typ) + { + SLOT->evs = 0; + } + else + { + SLOT->evm = ENV_MOD_RR; + SLOT->evs = SLOT->evsr; + } + break; + case ENV_MOD_RR: /* RR -> OFF */ + SLOT->evc = EG_OFF; + SLOT->eve = EG_OFF+1; + SLOT->evs = 0; + break; + } + } + /* calcrate envelope */ + return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0); +} + +/* set algorythm connection */ +static void set_algorythm( OPL_CH *CH) +{ + INT32 *carrier = &outd[0]; + CH->connect1 = CH->CON ? carrier : &feedback2; + CH->connect2 = carrier; +} + +/* ---------- frequency counter for operater update ---------- */ +INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT) +{ + int ksr; + + /* frequency step counter */ + SLOT->Incr = CH->fc * SLOT->mul; + ksr = CH->kcode >> SLOT->KSR; + + if( SLOT->ksr != ksr ) + { + SLOT->ksr = ksr; + /* attack , decay rate recalcration */ + SLOT->evsa = SLOT->AR[ksr]; + SLOT->evsd = SLOT->DR[ksr]; + SLOT->evsr = SLOT->RR[ksr]; + } + SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); +} + +/* set multi,am,vib,EG-TYP,KSR,mul */ +INLINE void set_mul(FM_OPL *OPL,int slot,int v) +{ + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + + SLOT->mul = MUL_TABLE[v&0x0f]; + SLOT->KSR = (v&0x10) ? 0 : 2; + SLOT->eg_typ = (v&0x20)>>5; + SLOT->vib = (v&0x40); + SLOT->ams = (v&0x80); + CALC_FCSLOT(CH,SLOT); +} + +/* set ksl & tl */ +INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v) +{ + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + int ksl = v>>6; /* 0 / 1.5 / 3 / 6 db/OCT */ + + SLOT->ksl = ksl ? 3-ksl : 31; + SLOT->TL = (v&0x3f)*(0.75/EG_STEP); /* 0.75db step */ + + if( !(OPL->mode&0x80) ) + { /* not CSM latch total level */ + SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); + } +} + +/* set attack rate & decay rate */ +INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v) +{ + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + int ar = v>>4; + int dr = v&0x0f; + + SLOT->AR = ar ? &OPL->AR_TABLE[ar<<2] : RATE_0; + SLOT->evsa = SLOT->AR[SLOT->ksr]; + if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa; + + SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0; + SLOT->evsd = SLOT->DR[SLOT->ksr]; + if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd; +} + +/* set sustain level & release rate */ +INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v) +{ + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + int sl = v>>4; + int rr = v & 0x0f; + + SLOT->SL = SL_TABLE[sl]; + if( SLOT->evm == ENV_MOD_DR ) SLOT->eve = SLOT->SL; + SLOT->RR = &OPL->DR_TABLE[rr<<2]; + SLOT->evsr = SLOT->RR[SLOT->ksr]; + if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr; +} + +/* operator output calcrator */ +#define OP_OUT(slot,env,con) slot->wavetable[((slot->Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env] +/* ---------- calcrate one of channel ---------- */ +INLINE void OPL_CALC_CH( OPL_CH *CH ) +{ + UINT32 env_out; + OPL_SLOT *SLOT; + + feedback2 = 0; + /* SLOT 1 */ + SLOT = &CH->SLOT[SLOT1]; + env_out=OPL_CALC_SLOT(SLOT); + if( env_out < EG_ENT-1 ) + { + /* PG */ + if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); + else SLOT->Cnt += SLOT->Incr; + /* connectoion */ + if(CH->FB) + { + int feedback1 = (CH->op1_out[0]+CH->op1_out[1])>>CH->FB; + CH->op1_out[1] = CH->op1_out[0]; + *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT,env_out,feedback1); + } + else + { + *CH->connect1 += OP_OUT(SLOT,env_out,0); + } + }else + { + CH->op1_out[1] = CH->op1_out[0]; + CH->op1_out[0] = 0; + } + /* SLOT 2 */ + SLOT = &CH->SLOT[SLOT2]; + env_out=OPL_CALC_SLOT(SLOT); + if( env_out < EG_ENT-1 ) + { + /* PG */ + if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); + else SLOT->Cnt += SLOT->Incr; + /* connectoion */ + outd[0] += OP_OUT(SLOT,env_out, feedback2); + } +} + +/* ---------- calcrate rythm block ---------- */ +#define WHITE_NOISE_db 6.0 +INLINE void OPL_CALC_RH( OPL_CH *CH ) +{ + UINT32 env_tam,env_sd,env_top,env_hh; + int whitenoise = (rand()&1)*(WHITE_NOISE_db/EG_STEP); + INT32 tone8; + + OPL_SLOT *SLOT; + int env_out; + + /* BD : same as FM serial mode and output level is large */ + feedback2 = 0; + /* SLOT 1 */ + SLOT = &CH[6].SLOT[SLOT1]; + env_out=OPL_CALC_SLOT(SLOT); + if( env_out < EG_ENT-1 ) + { + /* PG */ + if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); + else SLOT->Cnt += SLOT->Incr; + /* connectoion */ + if(CH[6].FB) + { + int feedback1 = (CH[6].op1_out[0]+CH[6].op1_out[1])>>CH[6].FB; + CH[6].op1_out[1] = CH[6].op1_out[0]; + feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT,env_out,feedback1); + } + else + { + feedback2 = OP_OUT(SLOT,env_out,0); + } + }else + { + feedback2 = 0; + CH[6].op1_out[1] = CH[6].op1_out[0]; + CH[6].op1_out[0] = 0; + } + /* SLOT 2 */ + SLOT = &CH[6].SLOT[SLOT2]; + env_out=OPL_CALC_SLOT(SLOT); + if( env_out < EG_ENT-1 ) + { + /* PG */ + if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); + else SLOT->Cnt += SLOT->Incr; + /* connectoion */ + outd[0] += OP_OUT(SLOT,env_out, feedback2)*2; + } + + // SD (17) = mul14[fnum7] + white noise + // TAM (15) = mul15[fnum8] + // TOP (18) = fnum6(mul18[fnum8]+whitenoise) + // HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise + env_sd =OPL_CALC_SLOT(SLOT7_2) + whitenoise; + env_tam=OPL_CALC_SLOT(SLOT8_1); + env_top=OPL_CALC_SLOT(SLOT8_2); + env_hh =OPL_CALC_SLOT(SLOT7_1) + whitenoise; + + /* PG */ + if(SLOT7_1->vib) SLOT7_1->Cnt += (2*SLOT7_1->Incr*vib/VIB_RATE); + else SLOT7_1->Cnt += 2*SLOT7_1->Incr; + if(SLOT7_2->vib) SLOT7_2->Cnt += ((CH[7].fc*8)*vib/VIB_RATE); + else SLOT7_2->Cnt += (CH[7].fc*8); + if(SLOT8_1->vib) SLOT8_1->Cnt += (SLOT8_1->Incr*vib/VIB_RATE); + else SLOT8_1->Cnt += SLOT8_1->Incr; + if(SLOT8_2->vib) SLOT8_2->Cnt += ((CH[8].fc*48)*vib/VIB_RATE); + else SLOT8_2->Cnt += (CH[8].fc*48); + + tone8 = OP_OUT(SLOT8_2,whitenoise,0 ); + + /* SD */ + if( env_sd < EG_ENT-1 ) + outd[0] += OP_OUT(SLOT7_1,env_sd, 0)*8; + /* TAM */ + if( env_tam < EG_ENT-1 ) + outd[0] += OP_OUT(SLOT8_1,env_tam, 0)*2; + /* TOP-CY */ + if( env_top < EG_ENT-1 ) + outd[0] += OP_OUT(SLOT7_2,env_top,tone8)*2; + /* HH */ + if( env_hh < EG_ENT-1 ) + outd[0] += OP_OUT(SLOT7_2,env_hh,tone8)*2; +} + +/* ----------- initialize time tabls ----------- */ +static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE ) +{ + int i; + double rate; + + /* make attack rate & decay rate tables */ + for (i = 0;i < 4;i++) OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0; + for (i = 4;i <= 60;i++){ + rate = OPL->freqbase; /* frequency rate */ + if( i < 60 ) rate *= 1.0+(i&3)*0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */ + rate *= 1<<((i>>2)-1); /* b2-5 : shift bit */ + rate *= (double)(EG_ENT<AR_TABLE[i] = rate / ARRATE; + OPL->DR_TABLE[i] = rate / DRRATE; + } + for (i = 60;i < 76;i++) + { + OPL->AR_TABLE[i] = EG_AED-1; + OPL->DR_TABLE[i] = OPL->DR_TABLE[60]; + } +#if 0 + for (i = 0;i < 64 ;i++){ /* make for overflow area */ + LOG(LOG_WAR,("rate %2d , ar %f ms , dr %f ms \n",i, + ((double)(EG_ENT<AR_TABLE[i]) * (1000.0 / OPL->rate), + ((double)(EG_ENT<DR_TABLE[i]) * (1000.0 / OPL->rate) )); + } +#endif +} + +/* ---------- generic table initialize ---------- */ +static int OPLOpenTable( void ) +{ + int s,t; + double rate; + int i,j; + double pom; + + /* allocate dynamic tables */ + if( (TL_TABLE = malloc(TL_MAX*2*sizeof(INT32))) == NULL) + return 0; + if( (SIN_TABLE = malloc(SIN_ENT*4 *sizeof(INT32 *))) == NULL) + { + free(TL_TABLE); + return 0; + } + if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(INT32))) == NULL) + { + free(TL_TABLE); + free(SIN_TABLE); + return 0; + } + if( (VIB_TABLE = malloc(VIB_ENT*2 *sizeof(INT32))) == NULL) + { + free(TL_TABLE); + free(SIN_TABLE); + free(AMS_TABLE); + return 0; + } + /* make total level table */ + for (t = 0;t < EG_ENT-1 ;t++){ + rate = ((1< voltage */ + TL_TABLE[ t] = (int)rate; + TL_TABLE[TL_MAX+t] = -TL_TABLE[t]; +/* LOG(LOG_INF,("TotalLevel(%3d) = %x\n",t,TL_TABLE[t]));*/ + } + /* fill volume off area */ + for ( t = EG_ENT-1; t < TL_MAX ;t++){ + TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0; + } + + /* make sinwave table (total level offet) */ + /* degree 0 = degree 180 = off */ + SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2] = &TL_TABLE[EG_ENT-1]; + for (s = 1;s <= SIN_ENT/4;s++){ + pom = sin(2*PI*s/SIN_ENT); /* sin */ + pom = 20*log10(1/pom); /* decibel */ + j = pom / EG_STEP; /* TL_TABLE steps */ + + /* degree 0 - 90 , degree 180 - 90 : plus section */ + SIN_TABLE[ s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j]; + /* degree 180 - 270 , degree 360 - 270 : minus section */ + SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT -s] = &TL_TABLE[TL_MAX+j]; +/* LOG(LOG_INF,("sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP));*/ + } + for (s = 0;s < SIN_ENT;s++) + { + SIN_TABLE[SIN_ENT*1+s] = s<(SIN_ENT/2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT]; + SIN_TABLE[SIN_ENT*2+s] = SIN_TABLE[s % (SIN_ENT/2)]; + SIN_TABLE[SIN_ENT*3+s] = (s/(SIN_ENT/4))&1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT*2+s]; + } + + /* envelope counter -> envelope output table */ + for (i=0; i= EG_ENT ) pom = EG_ENT-1; */ + ENV_CURVE[i] = (int)pom; + /* DECAY ,RELEASE curve */ + ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i; + } + /* off */ + ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1; + /* make LFO ams table */ + for (i=0; iSLOT[SLOT1]; + OPL_SLOT *slot2 = &CH->SLOT[SLOT2]; + /* all key off */ + OPL_KEYOFF(slot1); + OPL_KEYOFF(slot2); + /* total level latch */ + slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl); + slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl); + /* key on */ + CH->op1_out[0] = CH->op1_out[1] = 0; + OPL_KEYON(slot1); + OPL_KEYON(slot2); +} + +/* ---------- opl initialize ---------- */ +static void OPL_initalize(FM_OPL *OPL) +{ + int fn; + + /* frequency base */ + OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0; + /* Timer base time */ + OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 ); + /* make time tables */ + init_timetables( OPL , OPL_ARRATE , OPL_DRRATE ); + /* make fnumber -> increment counter table */ + for( fn=0 ; fn < 1024 ; fn++ ) + { + OPL->FN_TABLE[fn] = OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2; + } + /* LFO freq.table */ + OPL->amsIncr = OPL->rate ? (double)AMS_ENT*(1<rate * 3.7 * ((double)OPL->clock/3600000) : 0; + OPL->vibIncr = OPL->rate ? (double)VIB_ENT*(1<rate * 6.4 * ((double)OPL->clock/3600000) : 0; +} + +/* ---------- write a OPL registers ---------- */ +static void OPLWriteReg(FM_OPL *OPL, int r, int v) +{ + OPL_CH *CH; + int slot; + int block_fnum; + + switch(r&0xe0) + { + case 0x00: /* 00-1f:controll */ + switch(r&0x1f) + { + case 0x01: + /* wave selector enable */ + if(OPL->type&OPL_TYPE_WAVESEL) + { + OPL->wavesel = v&0x20; + if(!OPL->wavesel) + { + /* preset compatible mode */ + int c; + for(c=0;cmax_ch;c++) + { + OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0]; + OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0]; + } + } + } + return; + case 0x02: /* Timer 1 */ + OPL->T[0] = (256-v)*4; + break; + case 0x03: /* Timer 2 */ + OPL->T[1] = (256-v)*16; + return; + case 0x04: /* IRQ clear / mask and Timer enable */ + if(v&0x80) + { /* IRQ flag clear */ + OPL_STATUS_RESET(OPL,0x7f); + } + else + { /* set IRQ mask ,timer enable*/ + UINT8 st1 = v&1; + UINT8 st2 = (v>>1)&1; + /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */ + OPL_STATUS_RESET(OPL,v&0x78); + OPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01); + /* timer 2 */ + if(OPL->st[1] != st2) + { + double interval = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0; + OPL->st[1] = st2; + if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+1,interval); + } + /* timer 1 */ + if(OPL->st[0] != st1) + { + double interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0; + OPL->st[0] = st1; + if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval); + } + } + return; +#if BUILD_Y8950 + case 0x06: /* Key Board OUT */ + if(OPL->type&OPL_TYPE_KEYBOARD) + { + if(OPL->keyboardhandler_w) + OPL->keyboardhandler_w(OPL->keyboard_param,v); + else + LOG(LOG_WAR,("OPL:write unmapped KEYBOARD port\n")); + } + return; + case 0x07: /* DELTA-T controll : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */ + if(OPL->type&OPL_TYPE_ADPCM) + YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v); + return; + case 0x08: /* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */ + OPL->mode = v; + v&=0x1f; /* for DELTA-T unit */ + case 0x09: /* START ADD */ + case 0x0a: + case 0x0b: /* STOP ADD */ + case 0x0c: + case 0x0d: /* PRESCALE */ + case 0x0e: + case 0x0f: /* ADPCM data */ + case 0x10: /* DELTA-N */ + case 0x11: /* DELTA-N */ + case 0x12: /* EG-CTRL */ + if(OPL->type&OPL_TYPE_ADPCM) + YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v); + return; +#if 0 + case 0x15: /* DAC data */ + case 0x16: + case 0x17: /* SHIFT */ + return; + case 0x18: /* I/O CTRL (Direction) */ + if(OPL->type&OPL_TYPE_IO) + OPL->portDirection = v&0x0f; + return; + case 0x19: /* I/O DATA */ + if(OPL->type&OPL_TYPE_IO) + { + OPL->portLatch = v; + if(OPL->porthandler_w) + OPL->porthandler_w(OPL->port_param,v&OPL->portDirection); + } + return; + case 0x1a: /* PCM data */ + return; +#endif +#endif + } + break; + case 0x20: /* am,vib,ksr,eg type,mul */ + slot = slot_array[r&0x1f]; + if(slot == -1) return; + set_mul(OPL,slot,v); + return; + case 0x40: + slot = slot_array[r&0x1f]; + if(slot == -1) return; + set_ksl_tl(OPL,slot,v); + return; + case 0x60: + slot = slot_array[r&0x1f]; + if(slot == -1) return; + set_ar_dr(OPL,slot,v); + return; + case 0x80: + slot = slot_array[r&0x1f]; + if(slot == -1) return; + set_sl_rr(OPL,slot,v); + return; + case 0xa0: + switch(r) + { + case 0xbd: + /* amsep,vibdep,r,bd,sd,tom,tc,hh */ + { + UINT8 rkey = OPL->rythm^v; + OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0]; + OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0]; + OPL->rythm = v&0x3f; + if(OPL->rythm&0x20) + { +#if 0 + usrintf_showmessage("OPL Rythm mode select"); +#endif + /* BD key on/off */ + if(rkey&0x10) + { + if(v&0x10) + { + OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0; + OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]); + OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]); + } + else + { + OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]); + OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]); + } + } + /* SD key on/off */ + if(rkey&0x08) + { + if(v&0x08) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]); + else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]); + }/* TAM key on/off */ + if(rkey&0x04) + { + if(v&0x04) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]); + else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]); + } + /* TOP-CY key on/off */ + if(rkey&0x02) + { + if(v&0x02) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]); + else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]); + } + /* HH key on/off */ + if(rkey&0x01) + { + if(v&0x01) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]); + else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]); + } + } + } + return; + } + /* keyon,block,fnum */ + if( (r&0x0f) > 8) return; + CH = &OPL->P_CH[r&0x0f]; + if(!(r&0x10)) + { /* a0-a8 */ + block_fnum = (CH->block_fnum&0x1f00) | v; + } + else + { /* b0-b8 */ + int keyon = (v>>5)&1; + block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff); + if(CH->keyon != keyon) + { + if( (CH->keyon=keyon) ) + { + CH->op1_out[0] = CH->op1_out[1] = 0; + OPL_KEYON(&CH->SLOT[SLOT1]); + OPL_KEYON(&CH->SLOT[SLOT2]); + } + else + { + OPL_KEYOFF(&CH->SLOT[SLOT1]); + OPL_KEYOFF(&CH->SLOT[SLOT2]); + } + } + } + /* update */ + if(CH->block_fnum != block_fnum) + { + int blockRv = 7-(block_fnum>>10); + int fnum = block_fnum&0x3ff; + CH->block_fnum = block_fnum; + + CH->ksl_base = KSL_TABLE[block_fnum>>6]; + CH->fc = OPL->FN_TABLE[fnum]>>blockRv; + CH->kcode = CH->block_fnum>>9; + if( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1; + CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); + CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); + } + return; + case 0xc0: + /* FB,C */ + if( (r&0x0f) > 8) return; + CH = &OPL->P_CH[r&0x0f]; + { + int feedback = (v>>1)&7; + CH->FB = feedback ? (8+1) - feedback : 0; + CH->CON = v&1; + set_algorythm(CH); + } + return; + case 0xe0: /* wave type */ + slot = slot_array[r&0x1f]; + if(slot == -1) return; + CH = &OPL->P_CH[slot/2]; + if(OPL->wavesel) + { + /* LOG(LOG_INF,("OPL SLOT %d wave select %d\n",slot,v&3)); */ + CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT]; + } + return; + } +} + +/* lock/unlock for common table */ +static int OPL_LockTable(void) +{ + num_lock++; + if(num_lock>1) return 0; + /* first time */ + cur_chip = NULL; + /* allocate total level table (128kb space) */ + if( !OPLOpenTable() ) + { + num_lock--; + return -1; + } + return 0; +} + +static void OPL_UnLockTable(void) +{ + if(num_lock) num_lock--; + if(num_lock) return; + /* last time */ + cur_chip = NULL; + OPLCloseTable(); +} + +#if (BUILD_YM3812 || BUILD_YM3526) +/*******************************************************************************/ +/* YM3812 local section */ +/*******************************************************************************/ + +/* ---------- update one of chip ----------- */ +void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length) +{ + int i; + int data; + OPLSAMPLE *buf = buffer; + UINT32 amsCnt = OPL->amsCnt; + UINT32 vibCnt = OPL->vibCnt; + UINT8 rythm = OPL->rythm&0x20; + OPL_CH *CH,*R_CH; + + if( (void *)OPL != cur_chip ){ + cur_chip = (void *)OPL; + /* channel pointers */ + S_CH = OPL->P_CH; + E_CH = &S_CH[9]; + /* rythm slot */ + SLOT7_1 = &S_CH[7].SLOT[SLOT1]; + SLOT7_2 = &S_CH[7].SLOT[SLOT2]; + SLOT8_1 = &S_CH[8].SLOT[SLOT1]; + SLOT8_2 = &S_CH[8].SLOT[SLOT2]; + /* LFO state */ + amsIncr = OPL->amsIncr; + vibIncr = OPL->vibIncr; + ams_table = OPL->ams_table; + vib_table = OPL->vib_table; + } + R_CH = rythm ? &S_CH[6] : E_CH; + for( i=0; i < length ; i++ ) + { + /* channel A channel B channel C */ + /* LFO */ + ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT]; + vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT]; + outd[0] = 0; + /* FM part */ + for(CH=S_CH ; CH < R_CH ; CH++) + OPL_CALC_CH(CH); + /* Rythn part */ + if(rythm) + OPL_CALC_RH(S_CH); + /* limit check */ + data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT ); + /* store to sound buffer */ + buf[i] = data >> OPL_OUTSB; + } + + OPL->amsCnt = amsCnt; + OPL->vibCnt = vibCnt; +#ifdef OPL_OUTPUT_LOG + if(opl_dbg_fp) + { + for(opl_dbg_chip=0;opl_dbg_chipamsCnt; + UINT32 vibCnt = OPL->vibCnt; + UINT8 rythm = OPL->rythm&0x20; + OPL_CH *CH,*R_CH; + YM_DELTAT *DELTAT = OPL->deltat; + + /* setup DELTA-T unit */ + YM_DELTAT_DECODE_PRESET(DELTAT); + + if( (void *)OPL != cur_chip ){ + cur_chip = (void *)OPL; + /* channel pointers */ + S_CH = OPL->P_CH; + E_CH = &S_CH[9]; + /* rythm slot */ + SLOT7_1 = &S_CH[7].SLOT[SLOT1]; + SLOT7_2 = &S_CH[7].SLOT[SLOT2]; + SLOT8_1 = &S_CH[8].SLOT[SLOT1]; + SLOT8_2 = &S_CH[8].SLOT[SLOT2]; + /* LFO state */ + amsIncr = OPL->amsIncr; + vibIncr = OPL->vibIncr; + ams_table = OPL->ams_table; + vib_table = OPL->vib_table; + } + R_CH = rythm ? &S_CH[6] : E_CH; + for( i=0; i < length ; i++ ) + { + /* channel A channel B channel C */ + /* LFO */ + ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT]; + vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT]; + outd[0] = 0; + /* deltaT ADPCM */ + if( DELTAT->portstate ) + YM_DELTAT_ADPCM_CALC(DELTAT); + /* FM part */ + for(CH=S_CH ; CH < R_CH ; CH++) + OPL_CALC_CH(CH); + /* Rythn part */ + if(rythm) + OPL_CALC_RH(S_CH); + /* limit check */ + data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT ); + /* store to sound buffer */ + buf[i] = data >> OPL_OUTSB; + } + OPL->amsCnt = amsCnt; + OPL->vibCnt = vibCnt; + /* deltaT START flag */ + if( !DELTAT->portstate ) + OPL->status &= 0xfe; +} +#endif + +/* ---------- reset one of chip ---------- */ +void OPLResetChip(FM_OPL *OPL) +{ + int c,s; + int i; + + /* reset chip */ + OPL->mode = 0; /* normal mode */ + OPL_STATUS_RESET(OPL,0x7f); + /* reset with register write */ + OPLWriteReg(OPL,0x01,0); /* wabesel disable */ + OPLWriteReg(OPL,0x02,0); /* Timer1 */ + OPLWriteReg(OPL,0x03,0); /* Timer2 */ + OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */ + for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0); + /* reset OPerator paramater */ + for( c = 0 ; c < OPL->max_ch ; c++ ) + { + OPL_CH *CH = &OPL->P_CH[c]; + /* OPL->P_CH[c].PAN = OPN_CENTER; */ + for(s = 0 ; s < 2 ; s++ ) + { + /* wave table */ + CH->SLOT[s].wavetable = &SIN_TABLE[0]; + /* CH->SLOT[s].evm = ENV_MOD_RR; */ + CH->SLOT[s].evc = EG_OFF; + CH->SLOT[s].eve = EG_OFF+1; + CH->SLOT[s].evs = 0; + } + } +#if BUILD_Y8950 + if(OPL->type&OPL_TYPE_ADPCM) + { + YM_DELTAT *DELTAT = OPL->deltat; + + DELTAT->freqbase = OPL->freqbase; + DELTAT->output_pointer = outd; + DELTAT->portshift = 5; + DELTAT->output_range = DELTAT_MIXING_LEVEL<P_CH = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch; +#if BUILD_Y8950 + if(type&OPL_TYPE_ADPCM) OPL->deltat = (YM_DELTAT *)ptr; ptr+=sizeof(YM_DELTAT); +#endif + /* set channel state pointer */ + OPL->type = type; + OPL->clock = clock; + OPL->rate = rate; + OPL->max_ch = max_ch; + /* init grobal tables */ + OPL_initalize(OPL); + /* reset chip */ + OPLResetChip(OPL); +#ifdef OPL_OUTPUT_LOG + if(!opl_dbg_fp) + { + opl_dbg_fp = fopen("opllog.opl","wb"); + opl_dbg_maxchip = 0; + } + if(opl_dbg_fp) + { + opl_dbg_opl[opl_dbg_maxchip] = OPL; + fprintf(opl_dbg_fp,"%c%c%c%c%c%c",0x00+opl_dbg_maxchip, + type, + clock&0xff, + (clock/0x100)&0xff, + (clock/0x10000)&0xff, + (clock/0x1000000)&0xff); + opl_dbg_maxchip++; + } +#endif + return OPL; +} + +/* ---------- Destroy one of vietual YM3812 ---------- */ +void OPLDestroy(FM_OPL *OPL) +{ +#ifdef OPL_OUTPUT_LOG + if(opl_dbg_fp) + { + fclose(opl_dbg_fp); + opl_dbg_fp = NULL; + } +#endif + OPL_UnLockTable(); + free(OPL); +} + +/* ---------- Option handlers ---------- */ + +void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset) +{ + OPL->TimerHandler = TimerHandler; + OPL->TimerParam = channelOffset; +} +void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param) +{ + OPL->IRQHandler = IRQHandler; + OPL->IRQParam = param; +} +void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param) +{ + OPL->UpdateHandler = UpdateHandler; + OPL->UpdateParam = param; +} +#if BUILD_Y8950 +void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param) +{ + OPL->porthandler_w = PortHandler_w; + OPL->porthandler_r = PortHandler_r; + OPL->port_param = param; +} + +void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param) +{ + OPL->keyboardhandler_w = KeyboardHandler_w; + OPL->keyboardhandler_r = KeyboardHandler_r; + OPL->keyboard_param = param; +} +#endif +/* ---------- YM3812 I/O interface ---------- */ +int OPLWrite(FM_OPL *OPL,int a,int v) +{ + if( !(a&1) ) + { /* address port */ + OPL->address = v & 0xff; + } + else + { /* data port */ + if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); +#ifdef OPL_OUTPUT_LOG + if(opl_dbg_fp) + { + for(opl_dbg_chip=0;opl_dbg_chipaddress,v); + } +#endif + OPLWriteReg(OPL,OPL->address,v); + } + return OPL->status>>7; +} + +unsigned char OPLRead(FM_OPL *OPL,int a) +{ + if( !(a&1) ) + { /* status port */ + return OPL->status & (OPL->statusmask|0x80); + } + /* data port */ + switch(OPL->address) + { + case 0x05: /* KeyBoard IN */ + if(OPL->type&OPL_TYPE_KEYBOARD) + { + if(OPL->keyboardhandler_r) + return OPL->keyboardhandler_r(OPL->keyboard_param); + else + LOG(LOG_WAR,("OPL:read unmapped KEYBOARD port\n")); + } + return 0; +#if 0 + case 0x0f: /* ADPCM-DATA */ + return 0; +#endif + case 0x19: /* I/O DATA */ + if(OPL->type&OPL_TYPE_IO) + { + if(OPL->porthandler_r) + return OPL->porthandler_r(OPL->port_param); + else + LOG(LOG_WAR,("OPL:read unmapped I/O port\n")); + } + return 0; + case 0x1a: /* PCM-DATA */ + return 0; + } + return 0; +} + +int OPLTimerOver(FM_OPL *OPL,int c) +{ + if( c ) + { /* Timer B */ + OPL_STATUS_SET(OPL,0x20); + } + else + { /* Timer A */ + OPL_STATUS_SET(OPL,0x40); + /* CSM mode key,TL controll */ + if( OPL->mode & 0x80 ) + { /* CSM mode total level latch and auto key on */ + int ch; + if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); + for(ch=0;ch<9;ch++) + CSMKeyControll( &OPL->P_CH[ch] ); + } + } + /* reload timer */ + if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase); + return OPL->status>>7; +} diff --git a/tools/ioemu/hw/fmopl.h b/tools/ioemu/hw/fmopl.h new file mode 100644 index 0000000000..a01ff902c7 --- /dev/null +++ b/tools/ioemu/hw/fmopl.h @@ -0,0 +1,174 @@ +#ifndef __FMOPL_H_ +#define __FMOPL_H_ + +/* --- select emulation chips --- */ +#define BUILD_YM3812 (HAS_YM3812) +//#define BUILD_YM3526 (HAS_YM3526) +//#define BUILD_Y8950 (HAS_Y8950) + +/* --- system optimize --- */ +/* select bit size of output : 8 or 16 */ +#define OPL_OUTPUT_BIT 16 + +/* compiler dependence */ +#ifndef OSD_CPU_H +#define OSD_CPU_H +typedef unsigned char UINT8; /* unsigned 8bit */ +typedef unsigned short UINT16; /* unsigned 16bit */ +typedef unsigned int UINT32; /* unsigned 32bit */ +typedef signed char INT8; /* signed 8bit */ +typedef signed short INT16; /* signed 16bit */ +typedef signed int INT32; /* signed 32bit */ +#endif + +#if (OPL_OUTPUT_BIT==16) +typedef INT16 OPLSAMPLE; +#endif +#if (OPL_OUTPUT_BIT==8) +typedef unsigned char OPLSAMPLE; +#endif + + +#if BUILD_Y8950 +#include "ymdeltat.h" +#endif + +typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec); +typedef void (*OPL_IRQHANDLER)(int param,int irq); +typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us); +typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data); +typedef unsigned char (*OPL_PORTHANDLER_R)(int param); + +/* !!!!! here is private section , do not access there member direct !!!!! */ + +#define OPL_TYPE_WAVESEL 0x01 /* waveform select */ +#define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */ +#define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */ +#define OPL_TYPE_IO 0x08 /* I/O port */ + +/* Saving is necessary for member of the 'R' mark for suspend/resume */ +/* ---------- OPL one of slot ---------- */ +typedef struct fm_opl_slot { + INT32 TL; /* total level :TL << 8 */ + INT32 TLL; /* adjusted now TL */ + UINT8 KSR; /* key scale rate :(shift down bit) */ + INT32 *AR; /* attack rate :&AR_TABLE[AR<<2] */ + INT32 *DR; /* decay rate :&DR_TALBE[DR<<2] */ + INT32 SL; /* sustin level :SL_TALBE[SL] */ + INT32 *RR; /* release rate :&DR_TABLE[RR<<2] */ + UINT8 ksl; /* keyscale level :(shift down bits) */ + UINT8 ksr; /* key scale rate :kcode>>KSR */ + UINT32 mul; /* multiple :ML_TABLE[ML] */ + UINT32 Cnt; /* frequency count : */ + UINT32 Incr; /* frequency step : */ + /* envelope generator state */ + UINT8 eg_typ; /* envelope type flag */ + UINT8 evm; /* envelope phase */ + INT32 evc; /* envelope counter */ + INT32 eve; /* envelope counter end point */ + INT32 evs; /* envelope counter step */ + INT32 evsa; /* envelope step for AR :AR[ksr] */ + INT32 evsd; /* envelope step for DR :DR[ksr] */ + INT32 evsr; /* envelope step for RR :RR[ksr] */ + /* LFO */ + UINT8 ams; /* ams flag */ + UINT8 vib; /* vibrate flag */ + /* wave selector */ + INT32 **wavetable; +}OPL_SLOT; + +/* ---------- OPL one of channel ---------- */ +typedef struct fm_opl_channel { + OPL_SLOT SLOT[2]; + UINT8 CON; /* connection type */ + UINT8 FB; /* feed back :(shift down bit) */ + INT32 *connect1; /* slot1 output pointer */ + INT32 *connect2; /* slot2 output pointer */ + INT32 op1_out[2]; /* slot1 output for selfeedback */ + /* phase generator state */ + UINT32 block_fnum; /* block+fnum : */ + UINT8 kcode; /* key code : KeyScaleCode */ + UINT32 fc; /* Freq. Increment base */ + UINT32 ksl_base; /* KeyScaleLevel Base step */ + UINT8 keyon; /* key on/off flag */ +} OPL_CH; + +/* OPL state */ +typedef struct fm_opl_f { + UINT8 type; /* chip type */ + int clock; /* master clock (Hz) */ + int rate; /* sampling rate (Hz) */ + double freqbase; /* frequency base */ + double TimerBase; /* Timer base time (==sampling time) */ + UINT8 address; /* address register */ + UINT8 status; /* status flag */ + UINT8 statusmask; /* status mask */ + UINT32 mode; /* Reg.08 : CSM , notesel,etc. */ + /* Timer */ + int T[2]; /* timer counter */ + UINT8 st[2]; /* timer enable */ + /* FM channel slots */ + OPL_CH *P_CH; /* pointer of CH */ + int max_ch; /* maximum channel */ + /* Rythm sention */ + UINT8 rythm; /* Rythm mode , key flag */ +#if BUILD_Y8950 + /* Delta-T ADPCM unit (Y8950) */ + YM_DELTAT *deltat; /* DELTA-T ADPCM */ +#endif + /* Keyboard / I/O interface unit (Y8950) */ + UINT8 portDirection; + UINT8 portLatch; + OPL_PORTHANDLER_R porthandler_r; + OPL_PORTHANDLER_W porthandler_w; + int port_param; + OPL_PORTHANDLER_R keyboardhandler_r; + OPL_PORTHANDLER_W keyboardhandler_w; + int keyboard_param; + /* time tables */ + INT32 AR_TABLE[75]; /* atttack rate tables */ + INT32 DR_TABLE[75]; /* decay rate tables */ + UINT32 FN_TABLE[1024]; /* fnumber -> increment counter */ + /* LFO */ + INT32 *ams_table; + INT32 *vib_table; + INT32 amsCnt; + INT32 amsIncr; + INT32 vibCnt; + INT32 vibIncr; + /* wave selector enable flag */ + UINT8 wavesel; + /* external event callback handler */ + OPL_TIMERHANDLER TimerHandler; /* TIMER handler */ + int TimerParam; /* TIMER parameter */ + OPL_IRQHANDLER IRQHandler; /* IRQ handler */ + int IRQParam; /* IRQ parameter */ + OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */ + int UpdateParam; /* stream update parameter */ +} FM_OPL; + +/* ---------- Generic interface section ---------- */ +#define OPL_TYPE_YM3526 (0) +#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL) +#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO) + +FM_OPL *OPLCreate(int type, int clock, int rate); +void OPLDestroy(FM_OPL *OPL); +void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset); +void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param); +void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param); +/* Y8950 port handlers */ +void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param); +void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param); + +void OPLResetChip(FM_OPL *OPL); +int OPLWrite(FM_OPL *OPL,int a,int v); +unsigned char OPLRead(FM_OPL *OPL,int a); +int OPLTimerOver(FM_OPL *OPL,int c); + +/* YM3626/YM3812 local section */ +void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length); + +void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length); + +#endif diff --git a/tools/ioemu/hw/i8254.c b/tools/ioemu/hw/i8254.c new file mode 100644 index 0000000000..7fb91191cc --- /dev/null +++ b/tools/ioemu/hw/i8254.c @@ -0,0 +1,505 @@ +/* + * QEMU 8253/8254 interval timer emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" +#include "xc.h" +#include + +//#define DEBUG_PIT + +#define RW_STATE_LSB 1 +#define RW_STATE_MSB 2 +#define RW_STATE_WORD0 3 +#define RW_STATE_WORD1 4 + +typedef struct PITChannelState { + int count; /* can be 65536 */ + uint16_t latched_count; + uint8_t count_latched; + uint8_t status_latched; + uint8_t status; + uint8_t read_state; + uint8_t write_state; + uint8_t write_latch; + uint8_t rw_mode; + uint8_t mode; + uint8_t bcd; /* not supported */ + uint8_t gate; /* timer start */ + int64_t count_load_time; + /* irq handling */ + int64_t next_transition_time; + QEMUTimer *irq_timer; + int irq; +} PITChannelState; + +struct PITState { + PITChannelState channels[3]; +}; + +static PITState pit_state; + +static void pit_irq_timer_update(PITChannelState *s, int64_t current_time); + +/* currently operate which channel for vmx use */ +int vmx_channel = -1; +extern FILE *logfile; +static int pit_get_count(PITChannelState *s) +{ + uint64_t d; + int counter; + + d = muldiv64(qemu_get_clock(vm_clock) - s->count_load_time, PIT_FREQ, ticks_per_sec); + switch(s->mode) { + case 0: + case 1: + case 4: + case 5: + counter = (s->count - d) & 0xffff; + break; + case 3: + /* XXX: may be incorrect for odd counts */ + counter = s->count - ((2 * d) % s->count); + break; + default: + counter = s->count - (d % s->count); + break; + } + return counter; +} + +/* get pit output bit */ +static int pit_get_out1(PITChannelState *s, int64_t current_time) +{ + uint64_t d; + int out; + + d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec); + switch(s->mode) { + default: + case 0: + out = (d >= s->count); + break; + case 1: + out = (d < s->count); + break; + case 2: + if ((d % s->count) == 0 && d != 0) + out = 1; + else + out = 0; + break; + case 3: + out = (d % s->count) < ((s->count + 1) >> 1); + break; + case 4: + case 5: + out = (d == s->count); + break; + } + return out; +} + +int pit_get_out(PITState *pit, int channel, int64_t current_time) +{ + PITChannelState *s = &pit->channels[channel]; + return pit_get_out1(s, current_time); +} + +/* return -1 if no transition will occur. */ +static int64_t pit_get_next_transition_time(PITChannelState *s, + int64_t current_time) +{ + uint64_t d, next_time, base; + int period2; + + d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec); + switch(s->mode) { + default: + case 0: + case 1: + if (d < s->count) + next_time = s->count; + else + return -1; + break; + case 2: + base = (d / s->count) * s->count; + if ((d - base) == 0 && d != 0) + next_time = base + s->count; + else + next_time = base + s->count + 1; + break; + case 3: + base = (d / s->count) * s->count; + period2 = ((s->count + 1) >> 1); + if ((d - base) < period2) + next_time = base + period2; + else + next_time = base + s->count; + break; + case 4: + case 5: + if (d < s->count) + next_time = s->count; + else if (d == s->count) + next_time = s->count + 1; + else + return -1; + break; + } + /* convert to timer units */ + next_time = s->count_load_time + muldiv64(next_time, ticks_per_sec, PIT_FREQ); + /* fix potential rounding problems */ + /* XXX: better solution: use a clock at PIT_FREQ Hz */ + if (next_time <= current_time) + next_time = current_time + 1; + return next_time; +} + +/* val must be 0 or 1 */ +void pit_set_gate(PITState *pit, int channel, int val) +{ + PITChannelState *s = &pit->channels[channel]; + + switch(s->mode) { + default: + case 0: + case 4: + /* XXX: just disable/enable counting */ + break; + case 1: + case 5: + if (s->gate < val) { + /* restart counting on rising edge */ + s->count_load_time = qemu_get_clock(vm_clock); + pit_irq_timer_update(s, s->count_load_time); + } + break; + case 2: + case 3: + if (s->gate < val) { + /* restart counting on rising edge */ + s->count_load_time = qemu_get_clock(vm_clock); + pit_irq_timer_update(s, s->count_load_time); + } + /* XXX: disable/enable counting */ + break; + } + s->gate = val; +} + +int pit_get_gate(PITState *pit, int channel) +{ + PITChannelState *s = &pit->channels[channel]; + return s->gate; +} + +static inline void pit_load_count(PITChannelState *s, int val) +{ + extern void *shared_page; + ioreq_t *req; + int irq; + + if (val == 0) + val = 0x10000; + s->count_load_time = qemu_get_clock(vm_clock); + s->count = val; + + /* guest init this pit channel for periodic mode. we do not update related + * timer so the channel never send intr from device model*/ + if (vmx_channel != -1 && s->mode == 2) { + /* get the pit irq(0)'s vector from pic DM */ + if ((irq = pic_irq2vec(0)) >= 0) { + fprintf(logfile, + "VMX_PIT:guest init pit channel %d!\n", vmx_channel); + req = &((vcpu_iodata_t *) shared_page)->vp_ioreq; + + req->state = STATE_IORESP_HOOK; + /* + * info passed to HV as following + * -- init count:16 bit, timer vec:8 bit, + * PIT channel(0~2):2 bit, rw mode:2 bit + */ + req->u.data = s->count; + req->u.data |= (irq << 16); + req->u.data |= (vmx_channel << 24); + req->u.data |= ((s->rw_mode) << 26); + fprintf(logfile, "VMX_PIT:pass info 0x%llx to HV!\n", req->u.data); + vmx_channel = -1; + } + } + +/* pit_irq_timer_update(s, s->count_load_time);*/ +} + +/* if already latched, do not latch again */ +static void pit_latch_count(PITChannelState *s) +{ + if (!s->count_latched) { + s->latched_count = pit_get_count(s); + s->count_latched = s->rw_mode; + } +} + +static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ + PITState *pit = opaque; + int channel, access; + PITChannelState *s; + + addr &= 3; + if (addr == 3) { + channel = val >> 6; + if (channel == 3) { + /* read back command */ + for(channel = 0; channel < 3; channel++) { + s = &pit->channels[channel]; + if (val & (2 << channel)) { + if (!(val & 0x20)) { + pit_latch_count(s); + } + if (!(val & 0x10) && !s->status_latched) { + /* status latch */ + /* XXX: add BCD and null count */ + s->status = (pit_get_out1(s, qemu_get_clock(vm_clock)) << 7) | + (s->rw_mode << 4) | + (s->mode << 1) | + s->bcd; + s->status_latched = 1; + } + } + } + } else { + s = &pit->channels[channel]; + access = (val >> 4) & 3; + if (access == 0) { + pit_latch_count(s); + } else { + s->rw_mode = access; + s->read_state = access; + s->write_state = access; + + s->mode = (val >> 1) & 7; + s->bcd = val & 1; + /* XXX: update irq timer ? */ + } + } + } else { + s = &pit->channels[addr]; + vmx_channel = addr; + switch(s->write_state) { + default: + case RW_STATE_LSB: + pit_load_count(s, val); + break; + case RW_STATE_MSB: + pit_load_count(s, val << 8); + break; + case RW_STATE_WORD0: + s->write_latch = val; + s->write_state = RW_STATE_WORD1; + break; + case RW_STATE_WORD1: + pit_load_count(s, s->write_latch | (val << 8)); + s->write_state = RW_STATE_WORD0; + break; + } + } +} + +static uint32_t pit_ioport_read(void *opaque, uint32_t addr) +{ + PITState *pit = opaque; + int ret, count; + PITChannelState *s; + + addr &= 3; + s = &pit->channels[addr]; + if (s->status_latched) { + s->status_latched = 0; + ret = s->status; + } else if (s->count_latched) { + switch(s->count_latched) { + default: + case RW_STATE_LSB: + ret = s->latched_count & 0xff; + s->count_latched = 0; + break; + case RW_STATE_MSB: + ret = s->latched_count >> 8; + s->count_latched = 0; + break; + case RW_STATE_WORD0: + ret = s->latched_count & 0xff; + s->count_latched = RW_STATE_MSB; + break; + } + } else { + switch(s->read_state) { + default: + case RW_STATE_LSB: + count = pit_get_count(s); + ret = count & 0xff; + break; + case RW_STATE_MSB: + count = pit_get_count(s); + ret = (count >> 8) & 0xff; + break; + case RW_STATE_WORD0: + count = pit_get_count(s); + ret = count & 0xff; + s->read_state = RW_STATE_WORD1; + break; + case RW_STATE_WORD1: + count = pit_get_count(s); + ret = (count >> 8) & 0xff; + s->read_state = RW_STATE_WORD0; + break; + } + } + return ret; +} + +static void pit_irq_timer_update(PITChannelState *s, int64_t current_time) +{ + int64_t expire_time; + int irq_level; + + if (!s->irq_timer) + return; + expire_time = pit_get_next_transition_time(s, current_time); + irq_level = pit_get_out1(s, current_time); + pic_set_irq(s->irq, irq_level); +#ifdef DEBUG_PIT + printf("irq_level=%d next_delay=%f\n", + irq_level, + (double)(expire_time - current_time) / ticks_per_sec); +#endif + s->next_transition_time = expire_time; + if (expire_time != -1) + qemu_mod_timer(s->irq_timer, expire_time); + else + qemu_del_timer(s->irq_timer); +} + +static void pit_irq_timer(void *opaque) +{ + PITChannelState *s = opaque; + + pit_irq_timer_update(s, s->next_transition_time); +} + +static void pit_save(QEMUFile *f, void *opaque) +{ + PITState *pit = opaque; + PITChannelState *s; + int i; + + for(i = 0; i < 3; i++) { + s = &pit->channels[i]; + qemu_put_be32s(f, &s->count); + qemu_put_be16s(f, &s->latched_count); + qemu_put_8s(f, &s->count_latched); + qemu_put_8s(f, &s->status_latched); + qemu_put_8s(f, &s->status); + qemu_put_8s(f, &s->read_state); + qemu_put_8s(f, &s->write_state); + qemu_put_8s(f, &s->write_latch); + qemu_put_8s(f, &s->rw_mode); + qemu_put_8s(f, &s->mode); + qemu_put_8s(f, &s->bcd); + qemu_put_8s(f, &s->gate); + qemu_put_be64s(f, &s->count_load_time); + if (s->irq_timer) { + qemu_put_be64s(f, &s->next_transition_time); + qemu_put_timer(f, s->irq_timer); + } + } +} + +static int pit_load(QEMUFile *f, void *opaque, int version_id) +{ + PITState *pit = opaque; + PITChannelState *s; + int i; + + if (version_id != 1) + return -EINVAL; + + for(i = 0; i < 3; i++) { + s = &pit->channels[i]; + qemu_get_be32s(f, &s->count); + qemu_get_be16s(f, &s->latched_count); + qemu_get_8s(f, &s->count_latched); + qemu_get_8s(f, &s->status_latched); + qemu_get_8s(f, &s->status); + qemu_get_8s(f, &s->read_state); + qemu_get_8s(f, &s->write_state); + qemu_get_8s(f, &s->write_latch); + qemu_get_8s(f, &s->rw_mode); + qemu_get_8s(f, &s->mode); + qemu_get_8s(f, &s->bcd); + qemu_get_8s(f, &s->gate); + qemu_get_be64s(f, &s->count_load_time); + if (s->irq_timer) { + qemu_get_be64s(f, &s->next_transition_time); + qemu_get_timer(f, s->irq_timer); + } + } + return 0; +} + +static void pit_reset(void *opaque) +{ + PITState *pit = opaque; + PITChannelState *s; + int i; + + for(i = 0;i < 3; i++) { + s = &pit->channels[i]; + s->mode = 3; + s->gate = (i != 2); + pit_load_count(s, 0); + } +} + +PITState *pit_init(int base, int irq) +{ + PITState *pit = &pit_state; + PITChannelState *s; + + s = &pit->channels[0]; + /* the timer 0 is connected to an IRQ */ + s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s); + s->irq = irq; + + register_savevm("i8254", base, 1, pit_save, pit_load, pit); + + qemu_register_reset(pit_reset, pit); + register_ioport_write(base, 4, 1, pit_ioport_write, pit); + register_ioport_read(base, 3, 1, pit_ioport_read, pit); + + pit_reset(pit); + + return pit; +} diff --git a/tools/ioemu/hw/i8259.c b/tools/ioemu/hw/i8259.c new file mode 100644 index 0000000000..859c64bdf1 --- /dev/null +++ b/tools/ioemu/hw/i8259.c @@ -0,0 +1,528 @@ +/* + * QEMU 8259 interrupt controller emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +/* debug PIC */ +//#define DEBUG_PIC + +//#define DEBUG_IRQ_LATENCY +//#define DEBUG_IRQ_COUNT + +typedef struct PicState { + uint8_t last_irr; /* edge detection */ + uint8_t irr; /* interrupt request register */ + uint8_t imr; /* interrupt mask register */ + uint8_t isr; /* interrupt service register */ + uint8_t priority_add; /* highest irq priority */ + uint8_t irq_base; + uint8_t read_reg_select; + uint8_t poll; + uint8_t special_mask; + uint8_t init_state; + uint8_t auto_eoi; + uint8_t rotate_on_auto_eoi; + uint8_t special_fully_nested_mode; + uint8_t init4; /* true if 4 byte init */ + uint8_t elcr; /* PIIX edge/trigger selection*/ + uint8_t elcr_mask; +} PicState; + +/* 0 is master pic, 1 is slave pic */ +static PicState pics[2]; + +#if defined(DEBUG_PIC) || defined (DEBUG_IRQ_COUNT) +static int irq_level[16]; +#endif +#ifdef DEBUG_IRQ_COUNT +static uint64_t irq_count[16]; +#endif + +/* set irq level. If an edge is detected, then the IRR is set to 1 */ +static inline void pic_set_irq1(PicState *s, int irq, int level) +{ + int mask; + mask = 1 << irq; + if (s->elcr & mask) { + /* level triggered */ + if (level) { + s->irr |= mask; + s->last_irr |= mask; + } else { + s->irr &= ~mask; + s->last_irr &= ~mask; + } + } else { + /* edge triggered */ + if (level) { + if ((s->last_irr & mask) == 0) + s->irr |= mask; + s->last_irr |= mask; + } else { + s->last_irr &= ~mask; + } + } +} + +/* return the highest priority found in mask (highest = smallest + number). Return 8 if no irq */ +static inline int get_priority(PicState *s, int mask) +{ + int priority; + if (mask == 0) + return 8; + priority = 0; + while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0) + priority++; + return priority; +} + +/* return the pic wanted interrupt. return -1 if none */ +static int pic_get_irq(PicState *s) +{ + int mask, cur_priority, priority; + + mask = s->irr & ~s->imr; + priority = get_priority(s, mask); + if (priority == 8) + return -1; + /* compute current priority. If special fully nested mode on the + master, the IRQ coming from the slave is not taken into account + for the priority computation. */ + mask = s->isr; + if (s->special_fully_nested_mode && s == &pics[0]) + mask &= ~(1 << 2); + cur_priority = get_priority(s, mask); + if (priority < cur_priority) { + /* higher priority found: an irq should be generated */ + return (priority + s->priority_add) & 7; + } else { + return -1; + } +} + +/* raise irq to CPU if necessary. must be called every time the active + irq may change */ +static void pic_update_irq(void) +{ + int irq2, irq; + + /* first look at slave pic */ + irq2 = pic_get_irq(&pics[1]); + if (irq2 >= 0) { + /* if irq request by slave pic, signal master PIC */ + pic_set_irq1(&pics[0], 2, 1); + pic_set_irq1(&pics[0], 2, 0); + } + /* look at requested irq */ + irq = pic_get_irq(&pics[0]); + if (irq >= 0) { +#if defined(DEBUG_PIC) + { + int i; + for(i = 0; i < 2; i++) { + printf("pic%d: imr=%x irr=%x padd=%d\n", + i, pics[i].imr, pics[i].irr, pics[i].priority_add); + + } + } + printf("pic: cpu_interrupt\n"); +#endif + cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD); + } +} + +#ifdef DEBUG_IRQ_LATENCY +int64_t irq_time[16]; +#endif + +void pic_set_irq(int irq, int level) +{ +#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT) + if (level != irq_level[irq]) { +#if defined(DEBUG_PIC) + printf("pic_set_irq: irq=%d level=%d\n", irq, level); +#endif + irq_level[irq] = level; +#ifdef DEBUG_IRQ_COUNT + if (level == 1) + irq_count[irq]++; +#endif + } +#endif +#ifdef DEBUG_IRQ_LATENCY + if (level) { + irq_time[irq] = qemu_get_clock(vm_clock); + } +#endif + pic_set_irq1(&pics[irq >> 3], irq & 7, level); + pic_update_irq(); +} + +/* acknowledge interrupt 'irq' */ +static inline void pic_intack(PicState *s, int irq) +{ + if (s->auto_eoi) { + if (s->rotate_on_auto_eoi) + s->priority_add = (irq + 1) & 7; + } else { + s->isr |= (1 << irq); + } + /* We don't clear a level sensitive interrupt here */ + if (!(s->elcr & (1 << irq))) + s->irr &= ~(1 << irq); +} + +int cpu_get_pic_interrupt(CPUState *env) +{ + int irq, irq2, intno; + + /* read the irq from the PIC */ + + irq = pic_get_irq(&pics[0]); + if (irq >= 0) { + pic_intack(&pics[0], irq); + if (irq == 2) { + irq2 = pic_get_irq(&pics[1]); + if (irq2 >= 0) { + pic_intack(&pics[1], irq2); + } else { + /* spurious IRQ on slave controller */ + irq2 = 7; + } + intno = pics[1].irq_base + irq2; + irq = irq2 + 8; + } else { + intno = pics[0].irq_base + irq; + } + } else { + /* spurious IRQ on host controller */ + irq = 7; + intno = pics[0].irq_base + irq; + } + pic_update_irq(); + +#ifdef DEBUG_IRQ_LATENCY + printf("IRQ%d latency=%0.3fus\n", + irq, + (double)(qemu_get_clock(vm_clock) - irq_time[irq]) * 1000000.0 / ticks_per_sec); +#endif +#if defined(DEBUG_PIC) + printf("pic_interrupt: irq=%d\n", irq); +#endif + return intno; +} + +int pic_irq2vec(int irq) +{ + int vector = -1; + + if (irq >= 8 && irq <= 15) { + if (pics[1].irq_base != 0xFF) + vector = pics[1].irq_base + irq; + } else if (irq != 2 && irq <= 7) { + if (pics[0].irq_base != 0xFF) + vector = pics[0].irq_base + irq; + } + return vector; +} + +static void pic_reset(void *opaque) +{ + PicState *s = opaque; + int tmp; + + tmp = s->elcr_mask; + memset(s, 0, sizeof(PicState)); + s->elcr_mask = tmp; +} + +static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ + PicState *s = opaque; + int priority, cmd, irq; + +#ifdef DEBUG_PIC + printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val); +#endif + addr &= 1; + if (addr == 0) { + if (val & 0x10) { + /* init */ + pic_reset(s); + /* deassert a pending interrupt */ + cpu_reset_interrupt(cpu_single_env, CPU_INTERRUPT_HARD); + + s->init_state = 1; + s->init4 = val & 1; + if (val & 0x02) + hw_error("single mode not supported"); + if (val & 0x08) + hw_error("level sensitive irq not supported"); + } else if (val & 0x08) { + if (val & 0x04) + s->poll = 1; + if (val & 0x02) + s->read_reg_select = val & 1; + if (val & 0x40) + s->special_mask = (val >> 5) & 1; + } else { + cmd = val >> 5; + switch(cmd) { + case 0: + case 4: + s->rotate_on_auto_eoi = cmd >> 2; + break; + case 1: /* end of interrupt */ + case 5: + priority = get_priority(s, s->isr); + if (priority != 8) { + irq = (priority + s->priority_add) & 7; + s->isr &= ~(1 << irq); + if (cmd == 5) + s->priority_add = (irq + 1) & 7; + pic_update_irq(); + } + break; + case 3: + irq = val & 7; + s->isr &= ~(1 << irq); + pic_update_irq(); + break; + case 6: + s->priority_add = (val + 1) & 7; + pic_update_irq(); + break; + case 7: + irq = val & 7; + s->isr &= ~(1 << irq); + s->priority_add = (irq + 1) & 7; + pic_update_irq(); + break; + default: + /* no operation */ + break; + } + } + } else { + switch(s->init_state) { + case 0: + /* normal mode */ + s->imr = val; + pic_update_irq(); + break; + case 1: + s->irq_base = val & 0xf8; + s->init_state = 2; + break; + case 2: + if (s->init4) { + s->init_state = 3; + } else { + s->init_state = 0; + } + break; + case 3: + s->special_fully_nested_mode = (val >> 4) & 1; + s->auto_eoi = (val >> 1) & 1; + s->init_state = 0; + break; + } + } +} + +static uint32_t pic_poll_read (PicState *s, uint32_t addr1) +{ + int ret; + + ret = pic_get_irq(s); + if (ret >= 0) { + if (addr1 >> 7) { + pics[0].isr &= ~(1 << 2); + pics[0].irr &= ~(1 << 2); + } + s->irr &= ~(1 << ret); + s->isr &= ~(1 << ret); + if (addr1 >> 7 || ret != 2) + pic_update_irq(); + } else { + ret = 0x07; + pic_update_irq(); + } + + return ret; +} + +static uint32_t pic_ioport_read(void *opaque, uint32_t addr1) +{ + PicState *s = opaque; + unsigned int addr; + int ret; + + addr = addr1; + addr &= 1; + if (s->poll) { + ret = pic_poll_read(s, addr1); + s->poll = 0; + } else { + if (addr == 0) { + if (s->read_reg_select) + ret = s->isr; + else + ret = s->irr; + } else { + ret = s->imr; + } + } +#ifdef DEBUG_PIC + printf("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret); +#endif + return ret; +} + +/* memory mapped interrupt status */ +uint32_t pic_intack_read(CPUState *env) +{ + int ret; + + ret = pic_poll_read(&pics[0], 0x00); + if (ret == 2) + ret = pic_poll_read(&pics[1], 0x80) + 8; + /* Prepare for ISR read */ + pics[0].read_reg_select = 1; + + return ret; +} + +static void elcr_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ + PicState *s = opaque; + s->elcr = val & s->elcr_mask; +} + +static uint32_t elcr_ioport_read(void *opaque, uint32_t addr1) +{ + PicState *s = opaque; + return s->elcr; +} + +static void pic_save(QEMUFile *f, void *opaque) +{ + PicState *s = opaque; + + qemu_put_8s(f, &s->last_irr); + qemu_put_8s(f, &s->irr); + qemu_put_8s(f, &s->imr); + qemu_put_8s(f, &s->isr); + qemu_put_8s(f, &s->priority_add); + qemu_put_8s(f, &s->irq_base); + qemu_put_8s(f, &s->read_reg_select); + qemu_put_8s(f, &s->poll); + qemu_put_8s(f, &s->special_mask); + qemu_put_8s(f, &s->init_state); + qemu_put_8s(f, &s->auto_eoi); + qemu_put_8s(f, &s->rotate_on_auto_eoi); + qemu_put_8s(f, &s->special_fully_nested_mode); + qemu_put_8s(f, &s->init4); + qemu_put_8s(f, &s->elcr); +} + +static int pic_load(QEMUFile *f, void *opaque, int version_id) +{ + PicState *s = opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_8s(f, &s->last_irr); + qemu_get_8s(f, &s->irr); + qemu_get_8s(f, &s->imr); + qemu_get_8s(f, &s->isr); + qemu_get_8s(f, &s->priority_add); + qemu_get_8s(f, &s->irq_base); + qemu_get_8s(f, &s->read_reg_select); + qemu_get_8s(f, &s->poll); + qemu_get_8s(f, &s->special_mask); + qemu_get_8s(f, &s->init_state); + qemu_get_8s(f, &s->auto_eoi); + qemu_get_8s(f, &s->rotate_on_auto_eoi); + qemu_get_8s(f, &s->special_fully_nested_mode); + qemu_get_8s(f, &s->init4); + qemu_get_8s(f, &s->elcr); + return 0; +} + +/* XXX: add generic master/slave system */ +static void pic_init1(int io_addr, int elcr_addr, PicState *s) +{ + register_ioport_write(io_addr, 2, 1, pic_ioport_write, s); + register_ioport_read(io_addr, 2, 1, pic_ioport_read, s); + if (elcr_addr >= 0) { + register_ioport_write(elcr_addr, 1, 1, elcr_ioport_write, s); + register_ioport_read(elcr_addr, 1, 1, elcr_ioport_read, s); + } + register_savevm("i8259", io_addr, 1, pic_save, pic_load, s); + qemu_register_reset(pic_reset, s); +} + +void pic_info(void) +{ + int i; + PicState *s; + + for(i=0;i<2;i++) { + s = &pics[i]; + term_printf("pic%d: irr=%02x imr=%02x isr=%02x hprio=%d irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n", + i, s->irr, s->imr, s->isr, s->priority_add, + s->irq_base, s->read_reg_select, s->elcr, + s->special_fully_nested_mode); + } +} + +void irq_info(void) +{ +#ifndef DEBUG_IRQ_COUNT + term_printf("irq statistic code not compiled.\n"); +#else + int i; + int64_t count; + + term_printf("IRQ statistics:\n"); + for (i = 0; i < 16; i++) { + count = irq_count[i]; + if (count > 0) + term_printf("%2d: %lld\n", i, count); + } +#endif +} + +void pic_init(void) +{ + pic_init1(0x20, 0x4d0, &pics[0]); + pic_init1(0xa0, 0x4d1, &pics[1]); + pics[0].elcr_mask = 0xf8; + pics[1].elcr_mask = 0xde; + pics[0].irq_base = 0xff; + pics[0].irq_base = 0xff; +} + diff --git a/tools/ioemu/hw/ide.c b/tools/ioemu/hw/ide.c new file mode 100644 index 0000000000..bc7ebd3205 --- /dev/null +++ b/tools/ioemu/hw/ide.c @@ -0,0 +1,2318 @@ +/* + * QEMU IDE disk and CD-ROM Emulator + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +/* debug IDE devices */ +//#define DEBUG_IDE +//#define DEBUG_IDE_ATAPI + +/* Bits of HD_STATUS */ +#define ERR_STAT 0x01 +#define INDEX_STAT 0x02 +#define ECC_STAT 0x04 /* Corrected error */ +#define DRQ_STAT 0x08 +#define SEEK_STAT 0x10 +#define SRV_STAT 0x10 +#define WRERR_STAT 0x20 +#define READY_STAT 0x40 +#define BUSY_STAT 0x80 + +/* Bits for HD_ERROR */ +#define MARK_ERR 0x01 /* Bad address mark */ +#define TRK0_ERR 0x02 /* couldn't find track 0 */ +#define ABRT_ERR 0x04 /* Command aborted */ +#define MCR_ERR 0x08 /* media change request */ +#define ID_ERR 0x10 /* ID field not found */ +#define MC_ERR 0x20 /* media changed */ +#define ECC_ERR 0x40 /* Uncorrectable ECC error */ +#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */ +#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ + +/* Bits of HD_NSECTOR */ +#define CD 0x01 +#define IO 0x02 +#define REL 0x04 +#define TAG_MASK 0xf8 + +#define IDE_CMD_RESET 0x04 +#define IDE_CMD_DISABLE_IRQ 0x02 + +/* ATA/ATAPI Commands pre T13 Spec */ +#define WIN_NOP 0x00 +/* + * 0x01->0x02 Reserved + */ +#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */ +/* + * 0x04->0x07 Reserved + */ +#define WIN_SRST 0x08 /* ATAPI soft reset command */ +#define WIN_DEVICE_RESET 0x08 +/* + * 0x09->0x0F Reserved + */ +#define WIN_RECAL 0x10 +#define WIN_RESTORE WIN_RECAL +/* + * 0x10->0x1F Reserved + */ +#define WIN_READ 0x20 /* 28-Bit */ +#define WIN_READ_ONCE 0x21 /* 28-Bit without retries */ +#define WIN_READ_LONG 0x22 /* 28-Bit */ +#define WIN_READ_LONG_ONCE 0x23 /* 28-Bit without retries */ +#define WIN_READ_EXT 0x24 /* 48-Bit */ +#define WIN_READDMA_EXT 0x25 /* 48-Bit */ +#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */ +#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */ +/* + * 0x28 + */ +#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */ +/* + * 0x2A->0x2F Reserved + */ +#define WIN_WRITE 0x30 /* 28-Bit */ +#define WIN_WRITE_ONCE 0x31 /* 28-Bit without retries */ +#define WIN_WRITE_LONG 0x32 /* 28-Bit */ +#define WIN_WRITE_LONG_ONCE 0x33 /* 28-Bit without retries */ +#define WIN_WRITE_EXT 0x34 /* 48-Bit */ +#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */ +#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */ +#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */ +#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */ +#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */ +/* + * 0x3A->0x3B Reserved + */ +#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */ +/* + * 0x3D->0x3F Reserved + */ +#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */ +#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - without retries */ +#define WIN_VERIFY_EXT 0x42 /* 48-Bit */ +/* + * 0x43->0x4F Reserved + */ +#define WIN_FORMAT 0x50 +/* + * 0x51->0x5F Reserved + */ +#define WIN_INIT 0x60 +/* + * 0x61->0x5F Reserved + */ +#define WIN_SEEK 0x70 /* 0x70-0x7F Reserved */ +#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */ +#define WIN_DIAGNOSE 0x90 +#define WIN_SPECIFY 0x91 /* set drive geometry translation */ +#define WIN_DOWNLOAD_MICROCODE 0x92 +#define WIN_STANDBYNOW2 0x94 +#define WIN_STANDBY2 0x96 +#define WIN_SETIDLE2 0x97 +#define WIN_CHECKPOWERMODE2 0x98 +#define WIN_SLEEPNOW2 0x99 +/* + * 0x9A VENDOR + */ +#define WIN_PACKETCMD 0xA0 /* Send a packet command. */ +#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */ +#define WIN_QUEUED_SERVICE 0xA2 +#define WIN_SMART 0xB0 /* self-monitoring and reporting */ +#define CFA_ERASE_SECTORS 0xC0 +#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/ +#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */ +#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */ +#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */ +#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */ +#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - without retries */ +#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */ +#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - without retries */ +#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */ +#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */ +#define WIN_GETMEDIASTATUS 0xDA +#define WIN_ACKMEDIACHANGE 0xDB /* ATA-1, ATA-2 vendor */ +#define WIN_POSTBOOT 0xDC +#define WIN_PREBOOT 0xDD +#define WIN_DOORLOCK 0xDE /* lock door on removable drives */ +#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */ +#define WIN_STANDBYNOW1 0xE0 +#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */ +#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */ +#define WIN_SETIDLE1 0xE3 +#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */ +#define WIN_CHECKPOWERMODE1 0xE5 +#define WIN_SLEEPNOW1 0xE6 +#define WIN_FLUSH_CACHE 0xE7 +#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */ +#define WIN_WRITE_SAME 0xE9 /* read ata-2 to use */ + /* SET_FEATURES 0x22 or 0xDD */ +#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */ +#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */ +#define WIN_MEDIAEJECT 0xED +#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */ +#define WIN_SETFEATURES 0xEF /* set special drive features */ +#define EXABYTE_ENABLE_NEST 0xF0 +#define WIN_SECURITY_SET_PASS 0xF1 +#define WIN_SECURITY_UNLOCK 0xF2 +#define WIN_SECURITY_ERASE_PREPARE 0xF3 +#define WIN_SECURITY_ERASE_UNIT 0xF4 +#define WIN_SECURITY_FREEZE_LOCK 0xF5 +#define WIN_SECURITY_DISABLE 0xF6 +#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */ +#define WIN_SET_MAX 0xF9 +#define DISABLE_SEAGATE 0xFB + +/* set to 1 set disable mult support */ +#define MAX_MULT_SECTORS 16 + +/* ATAPI defines */ + +#define ATAPI_PACKET_SIZE 12 + +/* The generic packet command opcodes for CD/DVD Logical Units, + * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */ +#define GPCMD_BLANK 0xa1 +#define GPCMD_CLOSE_TRACK 0x5b +#define GPCMD_FLUSH_CACHE 0x35 +#define GPCMD_FORMAT_UNIT 0x04 +#define GPCMD_GET_CONFIGURATION 0x46 +#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a +#define GPCMD_GET_PERFORMANCE 0xac +#define GPCMD_INQUIRY 0x12 +#define GPCMD_LOAD_UNLOAD 0xa6 +#define GPCMD_MECHANISM_STATUS 0xbd +#define GPCMD_MODE_SELECT_10 0x55 +#define GPCMD_MODE_SENSE_10 0x5a +#define GPCMD_PAUSE_RESUME 0x4b +#define GPCMD_PLAY_AUDIO_10 0x45 +#define GPCMD_PLAY_AUDIO_MSF 0x47 +#define GPCMD_PLAY_AUDIO_TI 0x48 +#define GPCMD_PLAY_CD 0xbc +#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e +#define GPCMD_READ_10 0x28 +#define GPCMD_READ_12 0xa8 +#define GPCMD_READ_CDVD_CAPACITY 0x25 +#define GPCMD_READ_CD 0xbe +#define GPCMD_READ_CD_MSF 0xb9 +#define GPCMD_READ_DISC_INFO 0x51 +#define GPCMD_READ_DVD_STRUCTURE 0xad +#define GPCMD_READ_FORMAT_CAPACITIES 0x23 +#define GPCMD_READ_HEADER 0x44 +#define GPCMD_READ_TRACK_RZONE_INFO 0x52 +#define GPCMD_READ_SUBCHANNEL 0x42 +#define GPCMD_READ_TOC_PMA_ATIP 0x43 +#define GPCMD_REPAIR_RZONE_TRACK 0x58 +#define GPCMD_REPORT_KEY 0xa4 +#define GPCMD_REQUEST_SENSE 0x03 +#define GPCMD_RESERVE_RZONE_TRACK 0x53 +#define GPCMD_SCAN 0xba +#define GPCMD_SEEK 0x2b +#define GPCMD_SEND_DVD_STRUCTURE 0xad +#define GPCMD_SEND_EVENT 0xa2 +#define GPCMD_SEND_KEY 0xa3 +#define GPCMD_SEND_OPC 0x54 +#define GPCMD_SET_READ_AHEAD 0xa7 +#define GPCMD_SET_STREAMING 0xb6 +#define GPCMD_START_STOP_UNIT 0x1b +#define GPCMD_STOP_PLAY_SCAN 0x4e +#define GPCMD_TEST_UNIT_READY 0x00 +#define GPCMD_VERIFY_10 0x2f +#define GPCMD_WRITE_10 0x2a +#define GPCMD_WRITE_AND_VERIFY_10 0x2e +/* This is listed as optional in ATAPI 2.6, but is (curiously) + * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji + * Table 377 as an MMC command for SCSi devices though... Most ATAPI + * drives support it. */ +#define GPCMD_SET_SPEED 0xbb +/* This seems to be a SCSI specific CD-ROM opcode + * to play data at track/index */ +#define GPCMD_PLAYAUDIO_TI 0x48 +/* + * From MS Media Status Notification Support Specification. For + * older drives only. + */ +#define GPCMD_GET_MEDIA_STATUS 0xda + +/* Mode page codes for mode sense/set */ +#define GPMODE_R_W_ERROR_PAGE 0x01 +#define GPMODE_WRITE_PARMS_PAGE 0x05 +#define GPMODE_AUDIO_CTL_PAGE 0x0e +#define GPMODE_POWER_PAGE 0x1a +#define GPMODE_FAULT_FAIL_PAGE 0x1c +#define GPMODE_TO_PROTECT_PAGE 0x1d +#define GPMODE_CAPABILITIES_PAGE 0x2a +#define GPMODE_ALL_PAGES 0x3f +/* Not in Mt. Fuji, but in ATAPI 2.6 -- depricated now in favor + * of MODE_SENSE_POWER_PAGE */ +#define GPMODE_CDROM_PAGE 0x0d + +#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */ +#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */ +#define ATAPI_INT_REASON_REL 0x04 +#define ATAPI_INT_REASON_TAG 0xf8 + +/* same constants as bochs */ +#define ASC_ILLEGAL_OPCODE 0x20 +#define ASC_LOGICAL_BLOCK_OOR 0x21 +#define ASC_INV_FIELD_IN_CMD_PACKET 0x24 +#define ASC_MEDIUM_NOT_PRESENT 0x3a +#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39 + +#define SENSE_NONE 0 +#define SENSE_NOT_READY 2 +#define SENSE_ILLEGAL_REQUEST 5 +#define SENSE_UNIT_ATTENTION 6 + +struct IDEState; + +typedef void EndTransferFunc(struct IDEState *); + +/* NOTE: IDEState represents in fact one drive */ +typedef struct IDEState { + /* ide config */ + int is_cdrom; + int cylinders, heads, sectors; + int64_t nb_sectors; + int mult_sectors; + int irq; + openpic_t *openpic; + PCIDevice *pci_dev; + struct BMDMAState *bmdma; + int drive_serial; + /* ide regs */ + uint8_t feature; + uint8_t error; + uint16_t nsector; /* 0 is 256 to ease computations */ + uint8_t sector; + uint8_t lcyl; + uint8_t hcyl; + uint8_t select; + uint8_t status; + /* 0x3f6 command, only meaningful for drive 0 */ + uint8_t cmd; + /* depends on bit 4 in select, only meaningful for drive 0 */ + struct IDEState *cur_drive; + BlockDriverState *bs; + /* ATAPI specific */ + uint8_t sense_key; + uint8_t asc; + int packet_transfer_size; + int elementary_transfer_size; + int io_buffer_index; + int lba; + int cd_sector_size; + int atapi_dma; /* true if dma is requested for the packet cmd */ + /* ATA DMA state */ + int io_buffer_size; + /* PIO transfer handling */ + int req_nb_sectors; /* number of sectors per interrupt */ + EndTransferFunc *end_transfer_func; + uint8_t *data_ptr; + uint8_t *data_end; + uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4]; +} IDEState; + +#define BM_STATUS_DMAING 0x01 +#define BM_STATUS_ERROR 0x02 +#define BM_STATUS_INT 0x04 + +#define BM_CMD_START 0x01 +#define BM_CMD_READ 0x08 + +typedef int IDEDMAFunc(IDEState *s, + target_phys_addr_t phys_addr, + int transfer_size1); + +typedef struct BMDMAState { + uint8_t cmd; + uint8_t status; + uint32_t addr; + /* current transfer state */ + IDEState *ide_if; + IDEDMAFunc *dma_cb; +} BMDMAState; + +typedef struct PCIIDEState { + PCIDevice dev; + IDEState ide_if[4]; + BMDMAState bmdma[2]; +} PCIIDEState; + +static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb); + +static void padstr(char *str, const char *src, int len) +{ + int i, v; + for(i = 0; i < len; i++) { + if (*src) + v = *src++; + else + v = ' '; + *(char *)((long)str ^ 1) = v; + str++; + } +} + +static void padstr8(uint8_t *buf, int buf_size, const char *src) +{ + int i; + for(i = 0; i < buf_size; i++) { + if (*src) + buf[i] = *src++; + else + buf[i] = ' '; + } +} + +static void put_le16(uint16_t *p, unsigned int v) +{ + *p = cpu_to_le16(v); +} + +static void ide_identify(IDEState *s) +{ + uint16_t *p; + unsigned int oldsize; + char buf[20]; + + memset(s->io_buffer, 0, 512); + p = (uint16_t *)s->io_buffer; + put_le16(p + 0, 0x0040); + put_le16(p + 1, s->cylinders); + put_le16(p + 3, s->heads); + put_le16(p + 4, 512 * s->sectors); /* XXX: retired, remove ? */ + put_le16(p + 5, 512); /* XXX: retired, remove ? */ + put_le16(p + 6, s->sectors); + snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial); + padstr((uint8_t *)(p + 10), buf, 20); /* serial number */ + put_le16(p + 20, 3); /* XXX: retired, remove ? */ + put_le16(p + 21, 512); /* cache size in sectors */ + put_le16(p + 22, 4); /* ecc bytes */ + padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */ + padstr((uint8_t *)(p + 27), "QEMU HARDDISK", 40); /* model */ +#if MAX_MULT_SECTORS > 1 + put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS); +#endif + put_le16(p + 48, 1); /* dword I/O */ + put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */ + put_le16(p + 51, 0x200); /* PIO transfer cycle */ + put_le16(p + 52, 0x200); /* DMA transfer cycle */ + put_le16(p + 53, 1 | 1 << 2); /* words 54-58,88 are valid */ + put_le16(p + 54, s->cylinders); + put_le16(p + 55, s->heads); + put_le16(p + 56, s->sectors); + oldsize = s->cylinders * s->heads * s->sectors; + put_le16(p + 57, oldsize); + put_le16(p + 58, oldsize >> 16); + if (s->mult_sectors) + put_le16(p + 59, 0x100 | s->mult_sectors); + put_le16(p + 60, s->nb_sectors); + put_le16(p + 61, s->nb_sectors >> 16); + put_le16(p + 80, (1 << 1) | (1 << 2)); + put_le16(p + 82, (1 << 14)); + put_le16(p + 83, (1 << 14)); + put_le16(p + 84, (1 << 14)); + put_le16(p + 85, (1 << 14)); + put_le16(p + 86, 0); + put_le16(p + 87, (1 << 14)); + put_le16(p + 88, 0x1f | (1 << 13)); + put_le16(p + 93, 1 | (1 << 14) | 0x2000 | 0x4000); +} + +static void ide_atapi_identify(IDEState *s) +{ + uint16_t *p; + char buf[20]; + + memset(s->io_buffer, 0, 512); + p = (uint16_t *)s->io_buffer; + /* Removable CDROM, 50us response, 12 byte packets */ + put_le16(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0)); + snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial); + padstr((uint8_t *)(p + 10), buf, 20); /* serial number */ + put_le16(p + 20, 3); /* buffer type */ + put_le16(p + 21, 512); /* cache size in sectors */ + put_le16(p + 22, 4); /* ecc bytes */ + padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */ + padstr((uint8_t *)(p + 27), "QEMU CD-ROM", 40); /* model */ + put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */ + put_le16(p + 49, 1 << 9); /* LBA supported, no DMA */ + put_le16(p + 53, 3); /* words 64-70, 54-58 valid */ + put_le16(p + 63, 0x103); /* DMA modes XXX: may be incorrect */ + put_le16(p + 64, 1); /* PIO modes */ + put_le16(p + 65, 0xb4); /* minimum DMA multiword tx cycle time */ + put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */ + put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */ + put_le16(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control */ + + put_le16(p + 71, 30); /* in ns */ + put_le16(p + 72, 30); /* in ns */ + + put_le16(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */ +} + +static void ide_set_signature(IDEState *s) +{ + s->select &= 0xf0; /* clear head */ + /* put signature */ + s->nsector = 1; + s->sector = 1; + if (s->is_cdrom) { + s->lcyl = 0x14; + s->hcyl = 0xeb; + } else if (s->bs) { + s->lcyl = 0; + s->hcyl = 0; + } else { + s->lcyl = 0xff; + s->hcyl = 0xff; + } +} + +static inline void ide_abort_command(IDEState *s) +{ + s->status = READY_STAT | ERR_STAT; + s->error = ABRT_ERR; +} + +static inline void ide_set_irq(IDEState *s) +{ + if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) { +#ifdef TARGET_PPC + if (s->openpic) + openpic_set_irq(s->openpic, s->irq, 1); + else +#endif + if (s->irq == 16) + pci_set_irq(s->pci_dev, 0, 1); + else + pic_set_irq(s->irq, 1); + } +} + +/* prepare data transfer and tell what to do after */ +static void ide_transfer_start(IDEState *s, uint8_t *buf, int size, + EndTransferFunc *end_transfer_func) +{ + s->end_transfer_func = end_transfer_func; + s->data_ptr = buf; + s->data_end = buf + size; + s->status |= DRQ_STAT; +} + +static void ide_transfer_stop(IDEState *s) +{ + s->end_transfer_func = ide_transfer_stop; + s->data_ptr = s->io_buffer; + s->data_end = s->io_buffer; + s->status &= ~DRQ_STAT; +} + +static int64_t ide_get_sector(IDEState *s) +{ + int64_t sector_num; + if (s->select & 0x40) { + /* lba */ + sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) | + (s->lcyl << 8) | s->sector; + } else { + sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors + + (s->select & 0x0f) * s->sectors + + (s->sector - 1); + } + return sector_num; +} + +static void ide_set_sector(IDEState *s, int64_t sector_num) +{ + unsigned int cyl, r; + if (s->select & 0x40) { + s->select = (s->select & 0xf0) | (sector_num >> 24); + s->hcyl = (sector_num >> 16); + s->lcyl = (sector_num >> 8); + s->sector = (sector_num); + } else { + cyl = sector_num / (s->heads * s->sectors); + r = sector_num % (s->heads * s->sectors); + s->hcyl = cyl >> 8; + s->lcyl = cyl; + s->select = (s->select & 0xf0) | ((r / s->sectors) & 0x0f); + s->sector = (r % s->sectors) + 1; + } +} + +static void ide_sector_read(IDEState *s) +{ + int64_t sector_num; + int ret, n; + + s->status = READY_STAT | SEEK_STAT; + s->error = 0; /* not needed by IDE spec, but needed by Windows */ + sector_num = ide_get_sector(s); + n = s->nsector; + if (n == 0) { + /* no more sector to read from disk */ + ide_transfer_stop(s); + } else { +#if defined(DEBUG_IDE) + printf("read sector=%Ld\n", sector_num); +#endif + if (n > s->req_nb_sectors) + n = s->req_nb_sectors; + ret = bdrv_read(s->bs, sector_num, s->io_buffer, n); + ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read); + ide_set_irq(s); + ide_set_sector(s, sector_num + n); + s->nsector -= n; + } +} + +static int ide_read_dma_cb(IDEState *s, + target_phys_addr_t phys_addr, + int transfer_size1) +{ + int len, transfer_size, n; + int64_t sector_num; + + transfer_size = transfer_size1; + while (transfer_size > 0) { + len = s->io_buffer_size - s->io_buffer_index; + if (len <= 0) { + /* transfert next data */ + n = s->nsector; + if (n == 0) + break; + if (n > MAX_MULT_SECTORS) + n = MAX_MULT_SECTORS; + sector_num = ide_get_sector(s); + bdrv_read(s->bs, sector_num, s->io_buffer, n); + s->io_buffer_index = 0; + s->io_buffer_size = n * 512; + len = s->io_buffer_size; + sector_num += n; + ide_set_sector(s, sector_num); + s->nsector -= n; + } + if (len > transfer_size) + len = transfer_size; + cpu_physical_memory_write(phys_addr, + s->io_buffer + s->io_buffer_index, len); + s->io_buffer_index += len; + transfer_size -= len; + phys_addr += len; + } + if (s->io_buffer_index >= s->io_buffer_size && s->nsector == 0) { + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s); +#ifdef DEBUG_IDE_ATAPI + printf("dma status=0x%x\n", s->status); +#endif + return 0; + } + return transfer_size1 - transfer_size; +} + +static void ide_sector_read_dma(IDEState *s) +{ + s->status = READY_STAT | SEEK_STAT | DRQ_STAT; + s->io_buffer_index = 0; + s->io_buffer_size = 0; + ide_dma_start(s, ide_read_dma_cb); +} + +static void ide_sector_write(IDEState *s) +{ + int64_t sector_num; + int ret, n, n1; + + s->status = READY_STAT | SEEK_STAT; + sector_num = ide_get_sector(s); +#if defined(DEBUG_IDE) + printf("write sector=%Ld\n", sector_num); +#endif + n = s->nsector; + if (n > s->req_nb_sectors) + n = s->req_nb_sectors; + ret = bdrv_write(s->bs, sector_num, s->io_buffer, n); + s->nsector -= n; + if (s->nsector == 0) { + /* no more sector to write */ + ide_transfer_stop(s); + } else { + n1 = s->nsector; + if (n1 > s->req_nb_sectors) + n1 = s->req_nb_sectors; + ide_transfer_start(s, s->io_buffer, 512 * n1, ide_sector_write); + } + ide_set_sector(s, sector_num + n); + ide_set_irq(s); +} + +static int ide_write_dma_cb(IDEState *s, + target_phys_addr_t phys_addr, + int transfer_size1) +{ + int len, transfer_size, n; + int64_t sector_num; + + transfer_size = transfer_size1; + for(;;) { + len = s->io_buffer_size - s->io_buffer_index; + if (len == 0) { + n = s->io_buffer_size >> 9; + sector_num = ide_get_sector(s); + bdrv_write(s->bs, sector_num, s->io_buffer, + s->io_buffer_size >> 9); + sector_num += n; + ide_set_sector(s, sector_num); + s->nsector -= n; + n = s->nsector; + if (n == 0) { + /* end of transfer */ + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s); + return 0; + } + if (n > MAX_MULT_SECTORS) + n = MAX_MULT_SECTORS; + s->io_buffer_index = 0; + s->io_buffer_size = n * 512; + len = s->io_buffer_size; + } + if (transfer_size <= 0) + break; + if (len > transfer_size) + len = transfer_size; + cpu_physical_memory_read(phys_addr, + s->io_buffer + s->io_buffer_index, len); + s->io_buffer_index += len; + transfer_size -= len; + phys_addr += len; + } + return transfer_size1 - transfer_size; +} + +static void ide_sector_write_dma(IDEState *s) +{ + int n; + s->status = READY_STAT | SEEK_STAT | DRQ_STAT; + n = s->nsector; + if (n > MAX_MULT_SECTORS) + n = MAX_MULT_SECTORS; + s->io_buffer_index = 0; + s->io_buffer_size = n * 512; + ide_dma_start(s, ide_write_dma_cb); +} + +static void ide_atapi_cmd_ok(IDEState *s) +{ + s->error = 0; + s->status = READY_STAT; + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; + ide_set_irq(s); +} + +static void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc) +{ +#ifdef DEBUG_IDE_ATAPI + printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc); +#endif + s->error = sense_key << 4; + s->status = READY_STAT | ERR_STAT; + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; + s->sense_key = sense_key; + s->asc = asc; + ide_set_irq(s); +} + +static inline void cpu_to_ube16(uint8_t *buf, int val) +{ + buf[0] = val >> 8; + buf[1] = val; +} + +static inline void cpu_to_ube32(uint8_t *buf, unsigned int val) +{ + buf[0] = val >> 24; + buf[1] = val >> 16; + buf[2] = val >> 8; + buf[3] = val; +} + +static inline int ube16_to_cpu(const uint8_t *buf) +{ + return (buf[0] << 8) | buf[1]; +} + +static inline int ube32_to_cpu(const uint8_t *buf) +{ + return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; +} + +static void lba_to_msf(uint8_t *buf, int lba) +{ + lba += 150; + buf[0] = (lba / 75) / 60; + buf[1] = (lba / 75) % 60; + buf[2] = lba % 75; +} + +static void cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf, + int sector_size) +{ + switch(sector_size) { + case 2048: + bdrv_read(bs, (int64_t)lba << 2, buf, 4); + break; + case 2352: + /* sync bytes */ + buf[0] = 0x00; + memset(buf + 1, 0xff, 11); + buf += 12; + /* MSF */ + lba_to_msf(buf, lba); + buf[3] = 0x01; /* mode 1 data */ + buf += 4; + /* data */ + bdrv_read(bs, (int64_t)lba << 2, buf, 4); + buf += 2048; + /* ECC */ + memset(buf, 0, 288); + break; + default: + break; + } +} + +/* The whole ATAPI transfer logic is handled in this function */ +static void ide_atapi_cmd_reply_end(IDEState *s) +{ + int byte_count_limit, size; +#ifdef DEBUG_IDE_ATAPI + printf("reply: tx_size=%d elem_tx_size=%d index=%d\n", + s->packet_transfer_size, + s->elementary_transfer_size, + s->io_buffer_index); +#endif + if (s->packet_transfer_size <= 0) { + /* end of transfer */ + ide_transfer_stop(s); + s->status = READY_STAT; + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; + ide_set_irq(s); +#ifdef DEBUG_IDE_ATAPI + printf("status=0x%x\n", s->status); +#endif + } else { + /* see if a new sector must be read */ + if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) { + cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size); + s->lba++; + s->io_buffer_index = 0; + } + if (s->elementary_transfer_size > 0) { + /* there are some data left to transmit in this elementary + transfer */ + size = s->cd_sector_size - s->io_buffer_index; + if (size > s->elementary_transfer_size) + size = s->elementary_transfer_size; + ide_transfer_start(s, s->io_buffer + s->io_buffer_index, + size, ide_atapi_cmd_reply_end); + s->packet_transfer_size -= size; + s->elementary_transfer_size -= size; + s->io_buffer_index += size; + } else { + /* a new transfer is needed */ + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO; + byte_count_limit = s->lcyl | (s->hcyl << 8); +#ifdef DEBUG_IDE_ATAPI + printf("byte_count_limit=%d\n", byte_count_limit); +#endif + if (byte_count_limit == 0xffff) + byte_count_limit--; + size = s->packet_transfer_size; + if (size > byte_count_limit) { + /* byte count limit must be even if this case */ + if (byte_count_limit & 1) + byte_count_limit--; + size = byte_count_limit; + } + s->lcyl = size; + s->hcyl = size >> 8; + s->elementary_transfer_size = size; + /* we cannot transmit more than one sector at a time */ + if (s->lba != -1) { + if (size > (s->cd_sector_size - s->io_buffer_index)) + size = (s->cd_sector_size - s->io_buffer_index); + } + ide_transfer_start(s, s->io_buffer + s->io_buffer_index, + size, ide_atapi_cmd_reply_end); + s->packet_transfer_size -= size; + s->elementary_transfer_size -= size; + s->io_buffer_index += size; + ide_set_irq(s); +#ifdef DEBUG_IDE_ATAPI + printf("status=0x%x\n", s->status); +#endif + } + } +} + +/* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */ +static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size) +{ + if (size > max_size) + size = max_size; + s->lba = -1; /* no sector read */ + s->packet_transfer_size = size; + s->elementary_transfer_size = 0; + s->io_buffer_index = 0; + + s->status = READY_STAT; + ide_atapi_cmd_reply_end(s); +} + +/* start a CD-CDROM read command */ +static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors, + int sector_size) +{ + s->lba = lba; + s->packet_transfer_size = nb_sectors * sector_size; + s->elementary_transfer_size = 0; + s->io_buffer_index = sector_size; + s->cd_sector_size = sector_size; + + s->status = READY_STAT; + ide_atapi_cmd_reply_end(s); +} + +/* ATAPI DMA support */ +static int ide_atapi_cmd_read_dma_cb(IDEState *s, + target_phys_addr_t phys_addr, + int transfer_size1) +{ + int len, transfer_size; + + transfer_size = transfer_size1; + while (transfer_size > 0) { + if (s->packet_transfer_size <= 0) + break; + len = s->cd_sector_size - s->io_buffer_index; + if (len <= 0) { + /* transfert next data */ + cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size); + s->lba++; + s->io_buffer_index = 0; + len = s->cd_sector_size; + } + if (len > transfer_size) + len = transfer_size; + cpu_physical_memory_write(phys_addr, + s->io_buffer + s->io_buffer_index, len); + s->packet_transfer_size -= len; + s->io_buffer_index += len; + transfer_size -= len; + phys_addr += len; + } + if (s->packet_transfer_size <= 0) { + s->status = READY_STAT; + s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD; + ide_set_irq(s); +#ifdef DEBUG_IDE_ATAPI + printf("dma status=0x%x\n", s->status); +#endif + return 0; + } + return transfer_size1 - transfer_size; +} + +/* start a CD-CDROM read command with DMA */ +/* XXX: test if DMA is available */ +static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors, + int sector_size) +{ + s->lba = lba; + s->packet_transfer_size = nb_sectors * sector_size; + s->io_buffer_index = sector_size; + s->cd_sector_size = sector_size; + + s->status = READY_STAT | DRQ_STAT; + ide_dma_start(s, ide_atapi_cmd_read_dma_cb); +} + +static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors, + int sector_size) +{ +#ifdef DEBUG_IDE_ATAPI + printf("read: LBA=%d nb_sectors=%d\n", lba, nb_sectors); +#endif + if (s->atapi_dma) { + ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size); + } else { + ide_atapi_cmd_read_pio(s, lba, nb_sectors, sector_size); + } +} + +/* same toc as bochs. Return -1 if error or the toc length */ +/* XXX: check this */ +static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track) +{ + uint8_t *q; + int nb_sectors, len; + + if (start_track > 1 && start_track != 0xaa) + return -1; + q = buf + 2; + *q++ = 1; /* first session */ + *q++ = 1; /* last session */ + if (start_track <= 1) { + *q++ = 0; /* reserved */ + *q++ = 0x14; /* ADR, control */ + *q++ = 1; /* track number */ + *q++ = 0; /* reserved */ + if (msf) { + *q++ = 0; /* reserved */ + *q++ = 0; /* minute */ + *q++ = 2; /* second */ + *q++ = 0; /* frame */ + } else { + /* sector 0 */ + cpu_to_ube32(q, 0); + q += 4; + } + } + /* lead out track */ + *q++ = 0; /* reserved */ + *q++ = 0x16; /* ADR, control */ + *q++ = 0xaa; /* track number */ + *q++ = 0; /* reserved */ + nb_sectors = s->nb_sectors >> 2; + if (msf) { + *q++ = 0; /* reserved */ + lba_to_msf(q, nb_sectors); + q += 3; + } else { + cpu_to_ube32(q, nb_sectors); + q += 4; + } + len = q - buf; + cpu_to_ube16(buf, len - 2); + return len; +} + +/* mostly same info as PearPc */ +static int cdrom_read_toc_raw(IDEState *s, uint8_t *buf, int msf, + int session_num) +{ + uint8_t *q; + int nb_sectors, len; + + q = buf + 2; + *q++ = 1; /* first session */ + *q++ = 1; /* last session */ + + *q++ = 1; /* session number */ + *q++ = 0x14; /* data track */ + *q++ = 0; /* track number */ + *q++ = 0xa0; /* lead-in */ + *q++ = 0; /* min */ + *q++ = 0; /* sec */ + *q++ = 0; /* frame */ + *q++ = 0; + *q++ = 1; /* first track */ + *q++ = 0x00; /* disk type */ + *q++ = 0x00; + + *q++ = 1; /* session number */ + *q++ = 0x14; /* data track */ + *q++ = 0; /* track number */ + *q++ = 0xa1; + *q++ = 0; /* min */ + *q++ = 0; /* sec */ + *q++ = 0; /* frame */ + *q++ = 0; + *q++ = 1; /* last track */ + *q++ = 0x00; + *q++ = 0x00; + + *q++ = 1; /* session number */ + *q++ = 0x14; /* data track */ + *q++ = 0; /* track number */ + *q++ = 0xa2; /* lead-out */ + *q++ = 0; /* min */ + *q++ = 0; /* sec */ + *q++ = 0; /* frame */ + nb_sectors = s->nb_sectors >> 2; + if (msf) { + *q++ = 0; /* reserved */ + lba_to_msf(q, nb_sectors); + q += 3; + } else { + cpu_to_ube32(q, nb_sectors); + q += 4; + } + + *q++ = 1; /* session number */ + *q++ = 0x14; /* ADR, control */ + *q++ = 0; /* track number */ + *q++ = 1; /* point */ + *q++ = 0; /* min */ + *q++ = 0; /* sec */ + *q++ = 0; /* frame */ + *q++ = 0; + *q++ = 0; + *q++ = 0; + *q++ = 0; + + len = q - buf; + cpu_to_ube16(buf, len - 2); + return len; +} + +static void ide_atapi_cmd(IDEState *s) +{ + const uint8_t *packet; + uint8_t *buf; + int max_len; + + packet = s->io_buffer; + buf = s->io_buffer; +#ifdef DEBUG_IDE_ATAPI + { + int i; + printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8)); + for(i = 0; i < ATAPI_PACKET_SIZE; i++) { + printf(" %02x", packet[i]); + } + printf("\n"); + } +#endif + switch(s->io_buffer[0]) { + case GPCMD_TEST_UNIT_READY: + if (bdrv_is_inserted(s->bs)) { + ide_atapi_cmd_ok(s); + } else { + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + } + break; + case GPCMD_MODE_SENSE_10: + { + int action, code; + max_len = ube16_to_cpu(packet + 7); + action = packet[2] >> 6; + code = packet[2] & 0x3f; + switch(action) { + case 0: /* current values */ + switch(code) { + case 0x01: /* error recovery */ + cpu_to_ube16(&buf[0], 16 + 6); + buf[2] = 0x70; + buf[3] = 0; + buf[4] = 0; + buf[5] = 0; + buf[6] = 0; + buf[7] = 0; + + buf[8] = 0x01; + buf[9] = 0x06; + buf[10] = 0x00; + buf[11] = 0x05; + buf[12] = 0x00; + buf[13] = 0x00; + buf[14] = 0x00; + buf[15] = 0x00; + ide_atapi_cmd_reply(s, 16, max_len); + break; + case 0x2a: + cpu_to_ube16(&buf[0], 28 + 6); + buf[2] = 0x70; + buf[3] = 0; + buf[4] = 0; + buf[5] = 0; + buf[6] = 0; + buf[7] = 0; + + buf[8] = 0x2a; + buf[9] = 0x12; + buf[10] = 0x00; + buf[11] = 0x00; + + buf[12] = 0x70; + buf[13] = 3 << 5; + buf[14] = (1 << 0) | (1 << 3) | (1 << 5); + if (bdrv_is_locked(s->bs)) + buf[6] |= 1 << 1; + buf[15] = 0x00; + cpu_to_ube16(&buf[16], 706); + buf[18] = 0; + buf[19] = 2; + cpu_to_ube16(&buf[20], 512); + cpu_to_ube16(&buf[22], 706); + buf[24] = 0; + buf[25] = 0; + buf[26] = 0; + buf[27] = 0; + ide_atapi_cmd_reply(s, 28, max_len); + break; + default: + goto error_cmd; + } + break; + case 1: /* changeable values */ + goto error_cmd; + case 2: /* default values */ + goto error_cmd; + default: + case 3: /* saved values */ + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_SAVING_PARAMETERS_NOT_SUPPORTED); + break; + } + } + break; + case GPCMD_REQUEST_SENSE: + max_len = packet[4]; + memset(buf, 0, 18); + buf[0] = 0x70 | (1 << 7); + buf[2] = s->sense_key; + buf[7] = 10; + buf[12] = s->asc; + ide_atapi_cmd_reply(s, 18, max_len); + break; + case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL: + if (bdrv_is_inserted(s->bs)) { + bdrv_set_locked(s->bs, packet[4] & 1); + ide_atapi_cmd_ok(s); + } else { + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + } + break; + case GPCMD_READ_10: + case GPCMD_READ_12: + { + int nb_sectors, lba; + + if (!bdrv_is_inserted(s->bs)) { + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + break; + } + if (packet[0] == GPCMD_READ_10) + nb_sectors = ube16_to_cpu(packet + 7); + else + nb_sectors = ube32_to_cpu(packet + 6); + lba = ube32_to_cpu(packet + 2); + if (nb_sectors == 0) { + ide_atapi_cmd_ok(s); + break; + } + if (((int64_t)(lba + nb_sectors) << 2) > s->nb_sectors) { + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_LOGICAL_BLOCK_OOR); + break; + } + ide_atapi_cmd_read(s, lba, nb_sectors, 2048); + } + break; + case GPCMD_READ_CD: + { + int nb_sectors, lba, transfer_request; + + if (!bdrv_is_inserted(s->bs)) { + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + break; + } + nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8]; + lba = ube32_to_cpu(packet + 2); + if (nb_sectors == 0) { + ide_atapi_cmd_ok(s); + break; + } + if (((int64_t)(lba + nb_sectors) << 2) > s->nb_sectors) { + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_LOGICAL_BLOCK_OOR); + break; + } + transfer_request = packet[9]; + switch(transfer_request & 0xf8) { + case 0x00: + /* nothing */ + ide_atapi_cmd_ok(s); + break; + case 0x10: + /* normal read */ + ide_atapi_cmd_read(s, lba, nb_sectors, 2048); + break; + case 0xf8: + /* read all data */ + ide_atapi_cmd_read(s, lba, nb_sectors, 2352); + break; + default: + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET); + break; + } + } + break; + case GPCMD_SEEK: + { + int lba; + if (!bdrv_is_inserted(s->bs)) { + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + break; + } + lba = ube32_to_cpu(packet + 2); + if (((int64_t)lba << 2) > s->nb_sectors) { + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_LOGICAL_BLOCK_OOR); + break; + } + ide_atapi_cmd_ok(s); + } + break; + case GPCMD_START_STOP_UNIT: + { + int start, eject; + start = packet[4] & 1; + eject = (packet[4] >> 1) & 1; + + if (eject && !start) { + /* eject the disk */ + bdrv_close(s->bs); + } + ide_atapi_cmd_ok(s); + } + break; + case GPCMD_MECHANISM_STATUS: + { + max_len = ube16_to_cpu(packet + 8); + cpu_to_ube16(buf, 0); + /* no current LBA */ + buf[2] = 0; + buf[3] = 0; + buf[4] = 0; + buf[5] = 1; + cpu_to_ube16(buf + 6, 0); + ide_atapi_cmd_reply(s, 8, max_len); + } + break; + case GPCMD_READ_TOC_PMA_ATIP: + { + int format, msf, start_track, len; + + if (!bdrv_is_inserted(s->bs)) { + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + break; + } + max_len = ube16_to_cpu(packet + 7); + format = packet[9] >> 6; + msf = (packet[1] >> 1) & 1; + start_track = packet[6]; + switch(format) { + case 0: + len = cdrom_read_toc(s, buf, msf, start_track); + if (len < 0) + goto error_cmd; + ide_atapi_cmd_reply(s, len, max_len); + break; + case 1: + /* multi session : only a single session defined */ + memset(buf, 0, 12); + buf[1] = 0x0a; + buf[2] = 0x01; + buf[3] = 0x01; + ide_atapi_cmd_reply(s, 12, max_len); + break; + case 2: + len = cdrom_read_toc_raw(s, buf, msf, start_track); + if (len < 0) + goto error_cmd; + ide_atapi_cmd_reply(s, len, max_len); + break; + default: + error_cmd: + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_INV_FIELD_IN_CMD_PACKET); + break; + } + } + break; + case GPCMD_READ_CDVD_CAPACITY: + if (!bdrv_is_inserted(s->bs)) { + ide_atapi_cmd_error(s, SENSE_NOT_READY, + ASC_MEDIUM_NOT_PRESENT); + break; + } + /* NOTE: it is really the number of sectors minus 1 */ + cpu_to_ube32(buf, (s->nb_sectors >> 2) - 1); + cpu_to_ube32(buf + 4, 2048); + ide_atapi_cmd_reply(s, 8, 8); + break; + case GPCMD_INQUIRY: + max_len = packet[4]; + buf[0] = 0x05; /* CD-ROM */ + buf[1] = 0x80; /* removable */ + buf[2] = 0x00; /* ISO */ + buf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */ + buf[4] = 31; /* additionnal length */ + buf[5] = 0; /* reserved */ + buf[6] = 0; /* reserved */ + buf[7] = 0; /* reserved */ + padstr8(buf + 8, 8, "QEMU"); + padstr8(buf + 16, 16, "QEMU CD-ROM"); + padstr8(buf + 32, 4, QEMU_VERSION); + ide_atapi_cmd_reply(s, 36, max_len); + break; + default: + ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST, + ASC_ILLEGAL_OPCODE); + break; + } +} + +/* called when the inserted state of the media has changed */ +static void cdrom_change_cb(void *opaque) +{ + IDEState *s = opaque; + int64_t nb_sectors; + + /* XXX: send interrupt too */ + bdrv_get_geometry(s->bs, &nb_sectors); + s->nb_sectors = nb_sectors; +} + +static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ + IDEState *ide_if = opaque; + IDEState *s; + int unit, n; + +#ifdef DEBUG_IDE + printf("IDE: write addr=0x%x val=0x%02x\n", addr, val); +#endif + addr &= 7; + switch(addr) { + case 0: + break; + case 1: + /* NOTE: data is written to the two drives */ + ide_if[0].feature = val; + ide_if[1].feature = val; + break; + case 2: + if (val == 0) + val = 256; + ide_if[0].nsector = val; + ide_if[1].nsector = val; + break; + case 3: + ide_if[0].sector = val; + ide_if[1].sector = val; + break; + case 4: + ide_if[0].lcyl = val; + ide_if[1].lcyl = val; + break; + case 5: + ide_if[0].hcyl = val; + ide_if[1].hcyl = val; + break; + case 6: + ide_if[0].select = (val & ~0x10) | 0xa0; + ide_if[1].select = (val | 0x10) | 0xa0; + /* select drive */ + unit = (val >> 4) & 1; + s = ide_if + unit; + ide_if->cur_drive = s; + break; + default: + case 7: + /* command */ +#if defined(DEBUG_IDE) + printf("ide: CMD=%02x\n", val); +#endif + s = ide_if->cur_drive; + /* ignore commands to non existant slave */ + if (s != ide_if && !s->bs) + break; + switch(val) { + case WIN_IDENTIFY: + if (s->bs && !s->is_cdrom) { + ide_identify(s); + s->status = READY_STAT | SEEK_STAT; + ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop); + } else { + if (s->is_cdrom) { + ide_set_signature(s); + } + ide_abort_command(s); + } + ide_set_irq(s); + break; + case WIN_SPECIFY: + case WIN_RECAL: + s->error = 0; + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s); + break; + case WIN_SETMULT: + if (s->nsector > MAX_MULT_SECTORS || + s->nsector == 0 || + (s->nsector & (s->nsector - 1)) != 0) { + ide_abort_command(s); + } else { + s->mult_sectors = s->nsector; + s->status = READY_STAT; + } + ide_set_irq(s); + break; + case WIN_VERIFY: + case WIN_VERIFY_ONCE: + /* do sector number check ? */ + s->status = READY_STAT; + ide_set_irq(s); + break; + case WIN_READ: + case WIN_READ_ONCE: + if (!s->bs) + goto abort_cmd; + s->req_nb_sectors = 1; + ide_sector_read(s); + break; + case WIN_WRITE: + case WIN_WRITE_ONCE: + s->error = 0; + s->status = SEEK_STAT | READY_STAT; + s->req_nb_sectors = 1; + ide_transfer_start(s, s->io_buffer, 512, ide_sector_write); + break; + case WIN_MULTREAD: + if (!s->mult_sectors) + goto abort_cmd; + s->req_nb_sectors = s->mult_sectors; + ide_sector_read(s); + break; + case WIN_MULTWRITE: + if (!s->mult_sectors) + goto abort_cmd; + s->error = 0; + s->status = SEEK_STAT | READY_STAT; + s->req_nb_sectors = s->mult_sectors; + n = s->nsector; + if (n > s->req_nb_sectors) + n = s->req_nb_sectors; + ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write); + break; + case WIN_READDMA: + case WIN_READDMA_ONCE: + if (!s->bs) + goto abort_cmd; + ide_sector_read_dma(s); + break; + case WIN_WRITEDMA: + case WIN_WRITEDMA_ONCE: + if (!s->bs) + goto abort_cmd; + ide_sector_write_dma(s); + break; + case WIN_READ_NATIVE_MAX: + ide_set_sector(s, s->nb_sectors - 1); + s->status = READY_STAT; + ide_set_irq(s); + break; + case WIN_CHECKPOWERMODE1: + s->nsector = 0xff; /* device active or idle */ + s->status = READY_STAT; + ide_set_irq(s); + break; + case WIN_SETFEATURES: + if (!s->bs) + goto abort_cmd; + /* XXX: valid for CDROM ? */ + switch(s->feature) { + case 0x02: /* write cache enable */ + case 0x03: /* set transfer mode */ + case 0x82: /* write cache disable */ + case 0xaa: /* read look-ahead enable */ + case 0x55: /* read look-ahead disable */ + s->status = READY_STAT | SEEK_STAT; + ide_set_irq(s); + break; + default: + goto abort_cmd; + } + break; + case WIN_STANDBYNOW1: + s->status = READY_STAT; + ide_set_irq(s); + break; + /* ATAPI commands */ + case WIN_PIDENTIFY: + if (s->is_cdrom) { + ide_atapi_identify(s); + s->status = READY_STAT; + ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop); + } else { + ide_abort_command(s); + } + ide_set_irq(s); + break; + case WIN_SRST: + if (!s->is_cdrom) + goto abort_cmd; + ide_set_signature(s); + s->status = 0x00; /* NOTE: READY is _not_ set */ + s->error = 0x01; + break; + case WIN_PACKETCMD: + if (!s->is_cdrom) + goto abort_cmd; + /* overlapping commands not supported */ + if (s->feature & 0x02) + goto abort_cmd; + s->atapi_dma = s->feature & 1; + s->nsector = 1; + ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE, + ide_atapi_cmd); + break; + default: + abort_cmd: + ide_abort_command(s); + ide_set_irq(s); + break; + } + } +} + +static uint32_t ide_ioport_read(void *opaque, uint32_t addr1) +{ + IDEState *ide_if = opaque; + IDEState *s = ide_if->cur_drive; + uint32_t addr; + int ret; + + addr = addr1 & 7; + switch(addr) { + case 0: + ret = 0xff; + break; + case 1: + if (!ide_if[0].bs && !ide_if[1].bs) + ret = 0; + else + ret = s->error; + break; + case 2: + if (!ide_if[0].bs && !ide_if[1].bs) + ret = 0; + else + ret = s->nsector & 0xff; + break; + case 3: + if (!ide_if[0].bs && !ide_if[1].bs) + ret = 0; + else + ret = s->sector; + break; + case 4: + if (!ide_if[0].bs && !ide_if[1].bs) + ret = 0; + else + ret = s->lcyl; + break; + case 5: + if (!ide_if[0].bs && !ide_if[1].bs) + ret = 0; + else + ret = s->hcyl; + break; + case 6: + if (!ide_if[0].bs && !ide_if[1].bs) + ret = 0; + else + ret = s->select; + break; + default: + case 7: + if ((!ide_if[0].bs && !ide_if[1].bs) || + (s != ide_if && !s->bs)) + ret = 0; + else + ret = s->status; +#ifdef TARGET_PPC + if (s->openpic) + openpic_set_irq(s->openpic, s->irq, 0); + else +#endif + if (s->irq == 16) + pci_set_irq(s->pci_dev, 0, 0); + else + pic_set_irq(s->irq, 0); + break; + } +#ifdef DEBUG_IDE + printf("ide: read addr=0x%x val=%02x\n", addr1, ret); +#endif + return ret; +} + +static uint32_t ide_status_read(void *opaque, uint32_t addr) +{ + IDEState *ide_if = opaque; + IDEState *s = ide_if->cur_drive; + int ret; + + if ((!ide_if[0].bs && !ide_if[1].bs) || + (s != ide_if && !s->bs)) + ret = 0; + else + ret = s->status; +#ifdef DEBUG_IDE + printf("ide: read status addr=0x%x val=%02x\n", addr, ret); +#endif + return ret; +} + +static void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val) +{ + IDEState *ide_if = opaque; + IDEState *s; + int i; + +#ifdef DEBUG_IDE + printf("ide: write control addr=0x%x val=%02x\n", addr, val); +#endif + /* common for both drives */ + if (!(ide_if[0].cmd & IDE_CMD_RESET) && + (val & IDE_CMD_RESET)) { + /* reset low to high */ + for(i = 0;i < 2; i++) { + s = &ide_if[i]; + s->status = BUSY_STAT | SEEK_STAT; + s->error = 0x01; + } + } else if ((ide_if[0].cmd & IDE_CMD_RESET) && + !(val & IDE_CMD_RESET)) { + /* high to low */ + for(i = 0;i < 2; i++) { + s = &ide_if[i]; + if (s->is_cdrom) + s->status = 0x00; /* NOTE: READY is _not_ set */ + else + s->status = READY_STAT | SEEK_STAT; + ide_set_signature(s); + } + } + + ide_if[0].cmd = val; + ide_if[1].cmd = val; +} + +static void ide_data_writew(void *opaque, uint32_t addr, uint32_t val) +{ + IDEState *s = ((IDEState *)opaque)->cur_drive; + uint8_t *p; + + p = s->data_ptr; + *(uint16_t *)p = le16_to_cpu(val); + p += 2; + s->data_ptr = p; + if (p >= s->data_end) + s->end_transfer_func(s); +} + +static uint32_t ide_data_readw(void *opaque, uint32_t addr) +{ + IDEState *s = ((IDEState *)opaque)->cur_drive; + uint8_t *p; + int ret; + p = s->data_ptr; + ret = cpu_to_le16(*(uint16_t *)p); + p += 2; + s->data_ptr = p; + if (p >= s->data_end) + s->end_transfer_func(s); + return ret; +} + +static void ide_data_writel(void *opaque, uint32_t addr, uint32_t val) +{ + IDEState *s = ((IDEState *)opaque)->cur_drive; + uint8_t *p; + + p = s->data_ptr; + *(uint32_t *)p = le32_to_cpu(val); + p += 4; + s->data_ptr = p; + if (p >= s->data_end) + s->end_transfer_func(s); +} + +static uint32_t ide_data_readl(void *opaque, uint32_t addr) +{ + IDEState *s = ((IDEState *)opaque)->cur_drive; + uint8_t *p; + int ret; + + p = s->data_ptr; + ret = cpu_to_le32(*(uint32_t *)p); + p += 4; + s->data_ptr = p; + if (p >= s->data_end) + s->end_transfer_func(s); + return ret; +} + +static void ide_dummy_transfer_stop(IDEState *s) +{ + s->data_ptr = s->io_buffer; + s->data_end = s->io_buffer; + s->io_buffer[0] = 0xff; + s->io_buffer[1] = 0xff; + s->io_buffer[2] = 0xff; + s->io_buffer[3] = 0xff; +} + +static void ide_reset(IDEState *s) +{ + s->mult_sectors = MAX_MULT_SECTORS; + s->cur_drive = s; + s->select = 0xa0; + s->status = READY_STAT; + ide_set_signature(s); + /* init the transfer handler so that 0xffff is returned on data + accesses */ + s->end_transfer_func = ide_dummy_transfer_stop; + ide_dummy_transfer_stop(s); +} + +struct partition { + uint8_t boot_ind; /* 0x80 - active */ + uint8_t head; /* starting head */ + uint8_t sector; /* starting sector */ + uint8_t cyl; /* starting cylinder */ + uint8_t sys_ind; /* What partition type */ + uint8_t end_head; /* end head */ + uint8_t end_sector; /* end sector */ + uint8_t end_cyl; /* end cylinder */ + uint32_t start_sect; /* starting sector counting from 0 */ + uint32_t nr_sects; /* nr of sectors in partition */ +} __attribute__((packed)); + +/* try to guess the IDE geometry from the MSDOS partition table */ +static void ide_guess_geometry(IDEState *s) +{ + uint8_t buf[512]; + int ret, i; + struct partition *p; + uint32_t nr_sects; + + if (s->cylinders != 0) + return; + ret = bdrv_read(s->bs, 0, buf, 1); + if (ret < 0) + return; + /* test msdos magic */ + if (buf[510] != 0x55 || buf[511] != 0xaa) + return; + for(i = 0; i < 4; i++) { + p = ((struct partition *)(buf + 0x1be)) + i; + nr_sects = le32_to_cpu(p->nr_sects); + if (nr_sects && p->end_head) { + /* We make the assumption that the partition terminates on + a cylinder boundary */ + s->heads = p->end_head + 1; + s->sectors = p->end_sector & 63; + s->cylinders = s->nb_sectors / (s->heads * s->sectors); +#if 0 + printf("guessed partition: CHS=%d %d %d\n", + s->cylinders, s->heads, s->sectors); +#endif + } + } +} + +static void ide_init2(IDEState *ide_state, int irq, + BlockDriverState *hd0, BlockDriverState *hd1) +{ + IDEState *s; + static int drive_serial = 1; + int i, cylinders, heads, secs; + int64_t nb_sectors; + + for(i = 0; i < 2; i++) { + s = ide_state + i; + if (i == 0) + s->bs = hd0; + else + s->bs = hd1; + if (s->bs) { + bdrv_get_geometry(s->bs, &nb_sectors); + s->nb_sectors = nb_sectors; + /* if a geometry hint is available, use it */ + bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs); + if (cylinders != 0) { + s->cylinders = cylinders; + s->heads = heads; + s->sectors = secs; + } else { + ide_guess_geometry(s); + if (s->cylinders == 0) { + /* if no geometry, use a LBA compatible one */ + cylinders = nb_sectors / (16 * 63); + if (cylinders > 16383) + cylinders = 16383; + else if (cylinders < 2) + cylinders = 2; + s->cylinders = cylinders; + s->heads = 16; + s->sectors = 63; + } + bdrv_set_geometry_hint(s->bs, s->cylinders, s->heads, s->sectors); + } + if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) { + s->is_cdrom = 1; + bdrv_set_change_cb(s->bs, cdrom_change_cb, s); + } + } + s->drive_serial = drive_serial++; + s->irq = irq; + ide_reset(s); + } +} + +static void ide_init_ioport(IDEState *ide_state, int iobase, int iobase2) +{ + register_ioport_write(iobase, 8, 1, ide_ioport_write, ide_state); + register_ioport_read(iobase, 8, 1, ide_ioport_read, ide_state); + if (iobase2) { + register_ioport_read(iobase2, 1, 1, ide_status_read, ide_state); + register_ioport_write(iobase2, 1, 1, ide_cmd_write, ide_state); + } + + /* data ports */ + register_ioport_write(iobase, 2, 2, ide_data_writew, ide_state); + register_ioport_read(iobase, 2, 2, ide_data_readw, ide_state); + register_ioport_write(iobase, 4, 4, ide_data_writel, ide_state); + register_ioport_read(iobase, 4, 4, ide_data_readl, ide_state); +} + +/***********************************************************/ +/* ISA IDE definitions */ + +void isa_ide_init(int iobase, int iobase2, int irq, + BlockDriverState *hd0, BlockDriverState *hd1) +{ + IDEState *ide_state; + + ide_state = qemu_mallocz(sizeof(IDEState) * 2); + if (!ide_state) + return; + + ide_init2(ide_state, irq, hd0, hd1); + ide_init_ioport(ide_state, iobase, iobase2); +} + +/***********************************************************/ +/* PCI IDE definitions */ + +static void ide_map(PCIDevice *pci_dev, int region_num, + uint32_t addr, uint32_t size, int type) +{ + PCIIDEState *d = (PCIIDEState *)pci_dev; + IDEState *ide_state; + + if (region_num <= 3) { + ide_state = &d->ide_if[(region_num >> 1) * 2]; + if (region_num & 1) { + register_ioport_read(addr + 2, 1, 1, ide_status_read, ide_state); + register_ioport_write(addr + 2, 1, 1, ide_cmd_write, ide_state); + } else { + register_ioport_write(addr, 8, 1, ide_ioport_write, ide_state); + register_ioport_read(addr, 8, 1, ide_ioport_read, ide_state); + + /* data ports */ + register_ioport_write(addr, 2, 2, ide_data_writew, ide_state); + register_ioport_read(addr, 2, 2, ide_data_readw, ide_state); + register_ioport_write(addr, 4, 4, ide_data_writel, ide_state); + register_ioport_read(addr, 4, 4, ide_data_readl, ide_state); + } + } +} + +/* XXX: full callback usage to prepare non blocking I/Os support - + error handling */ +static void ide_dma_loop(BMDMAState *bm) +{ + struct { + uint32_t addr; + uint32_t size; + } prd; + target_phys_addr_t cur_addr; + int len, i, len1; + + cur_addr = bm->addr; + /* at most one page to avoid hanging if erroneous parameters */ + for(i = 0; i < 512; i++) { + cpu_physical_memory_read(cur_addr, (uint8_t *)&prd, 8); + prd.addr = le32_to_cpu(prd.addr); + prd.size = le32_to_cpu(prd.size); +#ifdef DEBUG_IDE + printf("ide: dma: prd: %08x: addr=0x%08x size=0x%08x\n", + (int)cur_addr, prd.addr, prd.size); +#endif + len = prd.size & 0xfffe; + if (len == 0) + len = 0x10000; + while (len > 0) { + len1 = bm->dma_cb(bm->ide_if, prd.addr, len); + if (len1 == 0) + goto the_end; + prd.addr += len1; + len -= len1; + } + /* end of transfer */ + if (prd.size & 0x80000000) + break; + cur_addr += 8; + } + /* end of transfer */ + the_end: + bm->status &= ~BM_STATUS_DMAING; + bm->status |= BM_STATUS_INT; + bm->dma_cb = NULL; + bm->ide_if = NULL; +} + +static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb) +{ + BMDMAState *bm = s->bmdma; + if(!bm) + return; + bm->ide_if = s; + bm->dma_cb = dma_cb; + if (bm->status & BM_STATUS_DMAING) { + ide_dma_loop(bm); + } +} + +static uint32_t bmdma_cmd_readb(void *opaque, uint32_t addr) +{ + BMDMAState *bm = opaque; + uint32_t val; + val = bm->cmd; +#ifdef DEBUG_IDE + printf("%s: 0x%08x\n", __func__, val); +#endif + return val; +} + +static void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val) +{ + BMDMAState *bm = opaque; +#ifdef DEBUG_IDE + printf("%s: 0x%08x\n", __func__, val); +#endif + if (!(val & BM_CMD_START)) { + /* XXX: do it better */ + bm->status &= ~BM_STATUS_DMAING; + bm->cmd = val & 0x09; + } else { + bm->status |= BM_STATUS_DMAING; + bm->cmd = val & 0x09; + /* start dma transfer if possible */ + if (bm->dma_cb) + ide_dma_loop(bm); + } +} + +static uint32_t bmdma_status_readb(void *opaque, uint32_t addr) +{ + BMDMAState *bm = opaque; + uint32_t val; + val = bm->status; +#ifdef DEBUG_IDE + printf("%s: 0x%08x\n", __func__, val); +#endif + return val; +} + +static void bmdma_status_writeb(void *opaque, uint32_t addr, uint32_t val) +{ + BMDMAState *bm = opaque; +#ifdef DEBUG_IDE + printf("%s: 0x%08x\n", __func__, val); +#endif + bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06); +} + +static uint32_t bmdma_addr_readl(void *opaque, uint32_t addr) +{ + BMDMAState *bm = opaque; + uint32_t val; + val = bm->addr; +#ifdef DEBUG_IDE + printf("%s: 0x%08x\n", __func__, val); +#endif + return val; +} + +static void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val) +{ + BMDMAState *bm = opaque; +#ifdef DEBUG_IDE + printf("%s: 0x%08x\n", __func__, val); +#endif + bm->addr = val & ~3; +} + +static void bmdma_map(PCIDevice *pci_dev, int region_num, + uint32_t addr, uint32_t size, int type) +{ + PCIIDEState *d = (PCIIDEState *)pci_dev; + int i; + + for(i = 0;i < 2; i++) { + BMDMAState *bm = &d->bmdma[i]; + d->ide_if[2 * i].bmdma = bm; + d->ide_if[2 * i + 1].bmdma = bm; + + register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm); + register_ioport_read(addr, 1, 1, bmdma_cmd_readb, bm); + + register_ioport_write(addr + 2, 1, 1, bmdma_status_writeb, bm); + register_ioport_read(addr + 2, 1, 1, bmdma_status_readb, bm); + + register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm); + register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm); + addr += 8; + } +} + +/* hd_table must contain 4 block drivers */ +void pci_ide_init(PCIBus *bus, BlockDriverState **hd_table) +{ + PCIIDEState *d; + uint8_t *pci_conf; + int i; + + d = (PCIIDEState *)pci_register_device(bus, "IDE", sizeof(PCIIDEState), + -1, + NULL, NULL); + pci_conf = d->dev.config; + pci_conf[0x00] = 0x86; // Intel + pci_conf[0x01] = 0x80; + pci_conf[0x02] = 0x00; // fake + pci_conf[0x03] = 0x01; // fake + pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE + pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage + pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic + + pci_conf[0x2c] = 0x86; // subsys vendor + pci_conf[0x2d] = 0x80; // subsys vendor + pci_conf[0x2e] = 0x00; // fake + pci_conf[0x2f] = 0x01; // fake + + pci_register_io_region((PCIDevice *)d, 0, 0x8, + PCI_ADDRESS_SPACE_IO, ide_map); + pci_register_io_region((PCIDevice *)d, 1, 0x4, + PCI_ADDRESS_SPACE_IO, ide_map); + pci_register_io_region((PCIDevice *)d, 2, 0x8, + PCI_ADDRESS_SPACE_IO, ide_map); + pci_register_io_region((PCIDevice *)d, 3, 0x4, + PCI_ADDRESS_SPACE_IO, ide_map); + pci_register_io_region((PCIDevice *)d, 4, 0x10, + PCI_ADDRESS_SPACE_IO, bmdma_map); + + pci_conf[0x3d] = 0x01; // interrupt on pin 1 + + for(i = 0; i < 4; i++) + d->ide_if[i].pci_dev = (PCIDevice *)d; + ide_init2(&d->ide_if[0], 16, hd_table[0], hd_table[1]); + ide_init2(&d->ide_if[2], 16, hd_table[2], hd_table[3]); +} + +/* hd_table must contain 4 block drivers */ +/* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */ +void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table) +{ + PCIIDEState *d; + uint8_t *pci_conf; + + /* register a function 1 of PIIX3 */ + d = (PCIIDEState *)pci_register_device(bus, "PIIX3 IDE", + sizeof(PCIIDEState), + ((PCIDevice *)piix3_state)->devfn + 1, + NULL, NULL); + pci_conf = d->dev.config; + pci_conf[0x00] = 0x86; // Intel + pci_conf[0x01] = 0x80; + pci_conf[0x02] = 0x10; + pci_conf[0x03] = 0x70; + pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE + pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage + pci_conf[0x0e] = 0x00; // header_type + + pci_register_io_region((PCIDevice *)d, 4, 0x10, + PCI_ADDRESS_SPACE_IO, bmdma_map); + + ide_init2(&d->ide_if[0], 14, hd_table[0], hd_table[1]); + ide_init2(&d->ide_if[2], 15, hd_table[2], hd_table[3]); + ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6); + ide_init_ioport(&d->ide_if[2], 0x170, 0x376); +} + +/***********************************************************/ +/* MacIO based PowerPC IDE */ + +/* PowerMac IDE memory IO */ +static void pmac_ide_writeb (void *opaque, + target_phys_addr_t addr, uint32_t val) +{ + addr = (addr & 0xFFF) >> 4; + switch (addr) { + case 1 ... 7: + ide_ioport_write(opaque, addr, val); + break; + case 8: + case 22: + ide_cmd_write(opaque, 0, val); + break; + default: + break; + } +} + +static uint32_t pmac_ide_readb (void *opaque,target_phys_addr_t addr) +{ + uint8_t retval; + + addr = (addr & 0xFFF) >> 4; + switch (addr) { + case 1 ... 7: + retval = ide_ioport_read(opaque, addr); + break; + case 8: + case 22: + retval = ide_status_read(opaque, 0); + break; + default: + retval = 0xFF; + break; + } + return retval; +} + +static void pmac_ide_writew (void *opaque, + target_phys_addr_t addr, uint32_t val) +{ + addr = (addr & 0xFFF) >> 4; +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap16(val); +#endif + if (addr == 0) { + ide_data_writew(opaque, 0, val); + } +} + +static uint32_t pmac_ide_readw (void *opaque,target_phys_addr_t addr) +{ + uint16_t retval; + + addr = (addr & 0xFFF) >> 4; + if (addr == 0) { + retval = ide_data_readw(opaque, 0); + } else { + retval = 0xFFFF; + } +#ifdef TARGET_WORDS_BIGENDIAN + retval = bswap16(retval); +#endif + return retval; +} + +static void pmac_ide_writel (void *opaque, + target_phys_addr_t addr, uint32_t val) +{ + addr = (addr & 0xFFF) >> 4; +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + if (addr == 0) { + ide_data_writel(opaque, 0, val); + } +} + +static uint32_t pmac_ide_readl (void *opaque,target_phys_addr_t addr) +{ + uint32_t retval; + + addr = (addr & 0xFFF) >> 4; + if (addr == 0) { + retval = ide_data_readl(opaque, 0); + } else { + retval = 0xFFFFFFFF; + } +#ifdef TARGET_WORDS_BIGENDIAN + retval = bswap32(retval); +#endif + return retval; +} + +static CPUWriteMemoryFunc *pmac_ide_write[] = { + pmac_ide_writeb, + pmac_ide_writew, + pmac_ide_writel, +}; + +static CPUReadMemoryFunc *pmac_ide_read[] = { + pmac_ide_readb, + pmac_ide_readw, + pmac_ide_readl, +}; + +/* hd_table must contain 4 block drivers */ +/* PowerMac uses memory mapped registers, not I/O. Return the memory + I/O index to access the ide. */ +int pmac_ide_init (BlockDriverState **hd_table, + openpic_t *openpic, int irq) +{ + IDEState *ide_if; + int pmac_ide_memory; + + ide_if = qemu_mallocz(sizeof(IDEState) * 2); + ide_init2(&ide_if[0], irq, hd_table[0], hd_table[1]); + ide_if[0].openpic = openpic; + ide_if[1].openpic = openpic; + + pmac_ide_memory = cpu_register_io_memory(0, pmac_ide_read, + pmac_ide_write, &ide_if[0]); + return pmac_ide_memory; +} diff --git a/tools/ioemu/hw/iommu.c b/tools/ioemu/hw/iommu.c new file mode 100644 index 0000000000..a9249c4ba7 --- /dev/null +++ b/tools/ioemu/hw/iommu.c @@ -0,0 +1,218 @@ +/* + * QEMU SPARC iommu emulation + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +/* debug iommu */ +//#define DEBUG_IOMMU + +/* The IOMMU registers occupy three pages in IO space. */ +struct iommu_regs { + /* First page */ + volatile unsigned long control; /* IOMMU control */ + volatile unsigned long base; /* Physical base of iopte page table */ + volatile unsigned long _unused1[3]; + volatile unsigned long tlbflush; /* write only */ + volatile unsigned long pageflush; /* write only */ + volatile unsigned long _unused2[1017]; + /* Second page */ + volatile unsigned long afsr; /* Async-fault status register */ + volatile unsigned long afar; /* Async-fault physical address */ + volatile unsigned long _unused3[2]; + volatile unsigned long sbuscfg0; /* SBUS configuration registers, per-slot */ + volatile unsigned long sbuscfg1; + volatile unsigned long sbuscfg2; + volatile unsigned long sbuscfg3; + volatile unsigned long mfsr; /* Memory-fault status register */ + volatile unsigned long mfar; /* Memory-fault physical address */ + volatile unsigned long _unused4[1014]; + /* Third page */ + volatile unsigned long mid; /* IOMMU module-id */ +}; + +#define IOMMU_CTRL_IMPL 0xf0000000 /* Implementation */ +#define IOMMU_CTRL_VERS 0x0f000000 /* Version */ +#define IOMMU_CTRL_RNGE 0x0000001c /* Mapping RANGE */ +#define IOMMU_RNGE_16MB 0x00000000 /* 0xff000000 -> 0xffffffff */ +#define IOMMU_RNGE_32MB 0x00000004 /* 0xfe000000 -> 0xffffffff */ +#define IOMMU_RNGE_64MB 0x00000008 /* 0xfc000000 -> 0xffffffff */ +#define IOMMU_RNGE_128MB 0x0000000c /* 0xf8000000 -> 0xffffffff */ +#define IOMMU_RNGE_256MB 0x00000010 /* 0xf0000000 -> 0xffffffff */ +#define IOMMU_RNGE_512MB 0x00000014 /* 0xe0000000 -> 0xffffffff */ +#define IOMMU_RNGE_1GB 0x00000018 /* 0xc0000000 -> 0xffffffff */ +#define IOMMU_RNGE_2GB 0x0000001c /* 0x80000000 -> 0xffffffff */ +#define IOMMU_CTRL_ENAB 0x00000001 /* IOMMU Enable */ + +#define IOMMU_AFSR_ERR 0x80000000 /* LE, TO, or BE asserted */ +#define IOMMU_AFSR_LE 0x40000000 /* SBUS reports error after transaction */ +#define IOMMU_AFSR_TO 0x20000000 /* Write access took more than 12.8 us. */ +#define IOMMU_AFSR_BE 0x10000000 /* Write access received error acknowledge */ +#define IOMMU_AFSR_SIZE 0x0e000000 /* Size of transaction causing error */ +#define IOMMU_AFSR_S 0x01000000 /* Sparc was in supervisor mode */ +#define IOMMU_AFSR_RESV 0x00f00000 /* Reserver, forced to 0x8 by hardware */ +#define IOMMU_AFSR_ME 0x00080000 /* Multiple errors occurred */ +#define IOMMU_AFSR_RD 0x00040000 /* A read operation was in progress */ +#define IOMMU_AFSR_FAV 0x00020000 /* IOMMU afar has valid contents */ + +#define IOMMU_SBCFG_SAB30 0x00010000 /* Phys-address bit 30 when bypass enabled */ +#define IOMMU_SBCFG_BA16 0x00000004 /* Slave supports 16 byte bursts */ +#define IOMMU_SBCFG_BA8 0x00000002 /* Slave supports 8 byte bursts */ +#define IOMMU_SBCFG_BYPASS 0x00000001 /* Bypass IOMMU, treat all addresses + produced by this device as pure + physical. */ + +#define IOMMU_MFSR_ERR 0x80000000 /* One or more of PERR1 or PERR0 */ +#define IOMMU_MFSR_S 0x01000000 /* Sparc was in supervisor mode */ +#define IOMMU_MFSR_CPU 0x00800000 /* CPU transaction caused parity error */ +#define IOMMU_MFSR_ME 0x00080000 /* Multiple parity errors occurred */ +#define IOMMU_MFSR_PERR 0x00006000 /* high bit indicates parity error occurred + on the even word of the access, low bit + indicated odd word caused the parity error */ +#define IOMMU_MFSR_BM 0x00001000 /* Error occurred while in boot mode */ +#define IOMMU_MFSR_C 0x00000800 /* Address causing error was marked cacheable */ +#define IOMMU_MFSR_RTYP 0x000000f0 /* Memory request transaction type */ + +#define IOMMU_MID_SBAE 0x001f0000 /* SBus arbitration enable */ +#define IOMMU_MID_SE 0x00100000 /* Enables SCSI/ETHERNET arbitration */ +#define IOMMU_MID_SB3 0x00080000 /* Enable SBUS device 3 arbitration */ +#define IOMMU_MID_SB2 0x00040000 /* Enable SBUS device 2 arbitration */ +#define IOMMU_MID_SB1 0x00020000 /* Enable SBUS device 1 arbitration */ +#define IOMMU_MID_SB0 0x00010000 /* Enable SBUS device 0 arbitration */ +#define IOMMU_MID_MID 0x0000000f /* Module-id, hardcoded to 0x8 */ + +/* The format of an iopte in the page tables */ +#define IOPTE_PAGE 0x07ffff00 /* Physical page number (PA[30:12]) */ +#define IOPTE_CACHE 0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */ +#define IOPTE_WRITE 0x00000004 /* Writeable */ +#define IOPTE_VALID 0x00000002 /* IOPTE is valid */ +#define IOPTE_WAZ 0x00000001 /* Write as zeros */ + +#define PAGE_SHIFT 12 +#define PAGE_SIZE (1 << PAGE_SHIFT) +#define PAGE_MASK (PAGE_SIZE - 1) + +typedef struct IOMMUState { + uint32_t addr; + uint32_t regs[sizeof(struct iommu_regs)]; + uint32_t iostart; +} IOMMUState; + +static IOMMUState *ps; + +static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr) +{ + IOMMUState *s = opaque; + uint32_t saddr; + + saddr = (addr - s->addr) >> 2; + switch (saddr) { + default: + return s->regs[saddr]; + break; + } + return 0; +} + +static void iommu_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + IOMMUState *s = opaque; + uint32_t saddr; + + saddr = (addr - s->addr) >> 2; + switch (saddr) { + case 0: + switch (val & IOMMU_CTRL_RNGE) { + case IOMMU_RNGE_16MB: + s->iostart = 0xff000000; + break; + case IOMMU_RNGE_32MB: + s->iostart = 0xfe000000; + break; + case IOMMU_RNGE_64MB: + s->iostart = 0xfc000000; + break; + case IOMMU_RNGE_128MB: + s->iostart = 0xf8000000; + break; + case IOMMU_RNGE_256MB: + s->iostart = 0xf0000000; + break; + case IOMMU_RNGE_512MB: + s->iostart = 0xe0000000; + break; + case IOMMU_RNGE_1GB: + s->iostart = 0xc0000000; + break; + default: + case IOMMU_RNGE_2GB: + s->iostart = 0x80000000; + break; + } + /* Fall through */ + default: + s->regs[saddr] = val; + break; + } +} + +static CPUReadMemoryFunc *iommu_mem_read[3] = { + iommu_mem_readw, + iommu_mem_readw, + iommu_mem_readw, +}; + +static CPUWriteMemoryFunc *iommu_mem_write[3] = { + iommu_mem_writew, + iommu_mem_writew, + iommu_mem_writew, +}; + +uint32_t iommu_translate(uint32_t addr) +{ + uint32_t *iopte = (void *)(ps->regs[1] << 4), pa; + + iopte += ((addr - ps->iostart) >> PAGE_SHIFT); + cpu_physical_memory_rw((uint32_t)iopte, (void *) &pa, 4, 0); + bswap32s(&pa); + pa = (pa & IOPTE_PAGE) << 4; /* Loose higher bits of 36 */ + return pa + (addr & PAGE_MASK); +} + +void iommu_init(uint32_t addr) +{ + IOMMUState *s; + int iommu_io_memory; + + s = qemu_mallocz(sizeof(IOMMUState)); + if (!s) + return; + + s->addr = addr; + + iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s); + cpu_register_physical_memory(addr, sizeof(struct iommu_regs), + iommu_io_memory); + + ps = s; +} + diff --git a/tools/ioemu/hw/lance.c b/tools/ioemu/hw/lance.c new file mode 100644 index 0000000000..25ad8c45b2 --- /dev/null +++ b/tools/ioemu/hw/lance.c @@ -0,0 +1,468 @@ +/* + * QEMU Lance emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +/* debug LANCE card */ +//#define DEBUG_LANCE + +#ifndef LANCE_LOG_TX_BUFFERS +#define LANCE_LOG_TX_BUFFERS 4 +#define LANCE_LOG_RX_BUFFERS 4 +#endif + +#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ +#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ + + +#define LE_CSR0 0 +#define LE_CSR1 1 +#define LE_CSR2 2 +#define LE_CSR3 3 +#define LE_MAXREG (LE_CSR3 + 1) + +#define LE_RDP 0 +#define LE_RAP 1 + +#define LE_MO_PROM 0x8000 /* Enable promiscuous mode */ + +#define LE_C0_ERR 0x8000 /* Error: set if BAB, SQE, MISS or ME is set */ +#define LE_C0_BABL 0x4000 /* BAB: Babble: tx timeout. */ +#define LE_C0_CERR 0x2000 /* SQE: Signal quality error */ +#define LE_C0_MISS 0x1000 /* MISS: Missed a packet */ +#define LE_C0_MERR 0x0800 /* ME: Memory error */ +#define LE_C0_RINT 0x0400 /* Received interrupt */ +#define LE_C0_TINT 0x0200 /* Transmitter Interrupt */ +#define LE_C0_IDON 0x0100 /* IFIN: Init finished. */ +#define LE_C0_INTR 0x0080 /* Interrupt or error */ +#define LE_C0_INEA 0x0040 /* Interrupt enable */ +#define LE_C0_RXON 0x0020 /* Receiver on */ +#define LE_C0_TXON 0x0010 /* Transmitter on */ +#define LE_C0_TDMD 0x0008 /* Transmitter demand */ +#define LE_C0_STOP 0x0004 /* Stop the card */ +#define LE_C0_STRT 0x0002 /* Start the card */ +#define LE_C0_INIT 0x0001 /* Init the card */ + +#define LE_C3_BSWP 0x4 /* SWAP */ +#define LE_C3_ACON 0x2 /* ALE Control */ +#define LE_C3_BCON 0x1 /* Byte control */ + +/* Receive message descriptor 1 */ +#define LE_R1_OWN 0x80 /* Who owns the entry */ +#define LE_R1_ERR 0x40 /* Error: if FRA, OFL, CRC or BUF is set */ +#define LE_R1_FRA 0x20 /* FRA: Frame error */ +#define LE_R1_OFL 0x10 /* OFL: Frame overflow */ +#define LE_R1_CRC 0x08 /* CRC error */ +#define LE_R1_BUF 0x04 /* BUF: Buffer error */ +#define LE_R1_SOP 0x02 /* Start of packet */ +#define LE_R1_EOP 0x01 /* End of packet */ +#define LE_R1_POK 0x03 /* Packet is complete: SOP + EOP */ + +#define LE_T1_OWN 0x80 /* Lance owns the packet */ +#define LE_T1_ERR 0x40 /* Error summary */ +#define LE_T1_EMORE 0x10 /* Error: more than one retry needed */ +#define LE_T1_EONE 0x08 /* Error: one retry needed */ +#define LE_T1_EDEF 0x04 /* Error: deferred */ +#define LE_T1_SOP 0x02 /* Start of packet */ +#define LE_T1_EOP 0x01 /* End of packet */ +#define LE_T1_POK 0x03 /* Packet is complete: SOP + EOP */ + +#define LE_T3_BUF 0x8000 /* Buffer error */ +#define LE_T3_UFL 0x4000 /* Error underflow */ +#define LE_T3_LCOL 0x1000 /* Error late collision */ +#define LE_T3_CLOS 0x0800 /* Error carrier loss */ +#define LE_T3_RTY 0x0400 /* Error retry */ +#define LE_T3_TDR 0x03ff /* Time Domain Reflectometry counter */ + +#define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS)) +#define TX_RING_MOD_MASK (TX_RING_SIZE - 1) +#define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29) + +#define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS)) +#define RX_RING_MOD_MASK (RX_RING_SIZE - 1) +#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29) + +#define PKT_BUF_SZ 1544 +#define RX_BUFF_SIZE PKT_BUF_SZ +#define TX_BUFF_SIZE PKT_BUF_SZ + +struct lance_rx_desc { + unsigned short rmd0; /* low address of packet */ + unsigned char rmd1_bits; /* descriptor bits */ + unsigned char rmd1_hadr; /* high address of packet */ + short length; /* This length is 2s complement (negative)! + * Buffer length + */ + unsigned short mblength; /* This is the actual number of bytes received */ +}; + +struct lance_tx_desc { + unsigned short tmd0; /* low address of packet */ + unsigned char tmd1_bits; /* descriptor bits */ + unsigned char tmd1_hadr; /* high address of packet */ + short length; /* Length is 2s complement (negative)! */ + unsigned short misc; +}; + +/* The LANCE initialization block, described in databook. */ +/* On the Sparc, this block should be on a DMA region */ +struct lance_init_block { + unsigned short mode; /* Pre-set mode (reg. 15) */ + unsigned char phys_addr[6]; /* Physical ethernet address */ + unsigned filter[2]; /* Multicast filter. */ + + /* Receive and transmit ring base, along with extra bits. */ + unsigned short rx_ptr; /* receive descriptor addr */ + unsigned short rx_len; /* receive len and high addr */ + unsigned short tx_ptr; /* transmit descriptor addr */ + unsigned short tx_len; /* transmit len and high addr */ + + /* The Tx and Rx ring entries must aligned on 8-byte boundaries. */ + struct lance_rx_desc brx_ring[RX_RING_SIZE]; + struct lance_tx_desc btx_ring[TX_RING_SIZE]; + + char tx_buf [TX_RING_SIZE][TX_BUFF_SIZE]; + char pad[2]; /* align rx_buf for copy_and_sum(). */ + char rx_buf [RX_RING_SIZE][RX_BUFF_SIZE]; +}; + +#define LEDMA_REGS 4 +#if 0 +/* Structure to describe the current status of DMA registers on the Sparc */ +struct sparc_dma_registers { + uint32_t cond_reg; /* DMA condition register */ + uint32_t st_addr; /* Start address of this transfer */ + uint32_t cnt; /* How many bytes to transfer */ + uint32_t dma_test; /* DMA test register */ +}; +#endif + +typedef struct LEDMAState { + uint32_t addr; + uint32_t regs[LEDMA_REGS]; +} LEDMAState; + +typedef struct LANCEState { + uint32_t paddr; + NetDriverState *nd; + uint32_t leptr; + uint16_t addr; + uint16_t regs[LE_MAXREG]; + uint8_t phys[6]; /* mac address */ + int irq; + LEDMAState *ledma; +} LANCEState; + +static unsigned int rxptr, txptr; + +static void lance_send(void *opaque); + +static void lance_reset(LANCEState *s) +{ + memcpy(s->phys, s->nd->macaddr, 6); + rxptr = 0; + txptr = 0; + s->regs[LE_CSR0] = LE_C0_STOP; +} + +static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr) +{ + LANCEState *s = opaque; + uint32_t saddr; + + saddr = addr - s->paddr; + switch (saddr >> 1) { + case LE_RDP: + return s->regs[s->addr]; + case LE_RAP: + return s->addr; + default: + break; + } + return 0; +} + +static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + LANCEState *s = opaque; + uint32_t saddr; + uint16_t reg; + + saddr = addr - s->paddr; + switch (saddr >> 1) { + case LE_RDP: + switch(s->addr) { + case LE_CSR0: + if (val & LE_C0_STOP) { + s->regs[LE_CSR0] = LE_C0_STOP; + break; + } + + reg = s->regs[LE_CSR0]; + + // 1 = clear for some bits + reg &= ~(val & 0x7f00); + + // generated bits + reg &= ~(LE_C0_ERR | LE_C0_INTR); + if (reg & 0x7100) + reg |= LE_C0_ERR; + if (reg & 0x7f00) + reg |= LE_C0_INTR; + + // direct bit + reg &= ~LE_C0_INEA; + reg |= val & LE_C0_INEA; + + // exclusive bits + if (val & LE_C0_INIT) { + reg |= LE_C0_IDON | LE_C0_INIT; + reg &= ~LE_C0_STOP; + } + else if (val & LE_C0_STRT) { + reg |= LE_C0_STRT | LE_C0_RXON | LE_C0_TXON; + reg &= ~LE_C0_STOP; + } + + s->regs[LE_CSR0] = reg; + + // trigger bits + //if (val & LE_C0_TDMD) + + if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA)) + pic_set_irq(s->irq, 1); + break; + case LE_CSR1: + s->leptr = (s->leptr & 0xffff0000) | (val & 0xffff); + s->regs[s->addr] = val; + break; + case LE_CSR2: + s->leptr = (s->leptr & 0xffff) | ((val & 0xffff) << 16); + s->regs[s->addr] = val; + break; + case LE_CSR3: + s->regs[s->addr] = val; + break; + } + break; + case LE_RAP: + if (val < LE_MAXREG) + s->addr = val; + break; + default: + break; + } + lance_send(s); +} + +static CPUReadMemoryFunc *lance_mem_read[3] = { + lance_mem_readw, + lance_mem_readw, + lance_mem_readw, +}; + +static CPUWriteMemoryFunc *lance_mem_write[3] = { + lance_mem_writew, + lance_mem_writew, + lance_mem_writew, +}; + + +/* return the max buffer size if the LANCE can receive more data */ +static int lance_can_receive(void *opaque) +{ + LANCEState *s = opaque; + void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]); + struct lance_init_block *ib; + int i; + uint16_t temp; + + if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP) + return 0; + + ib = (void *) iommu_translate(dmaptr); + + for (i = 0; i < RX_RING_SIZE; i++) { + cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1); + temp &= 0xff; + if (temp == (LE_R1_OWN)) { +#ifdef DEBUG_LANCE + fprintf(stderr, "lance: can receive %d\n", RX_BUFF_SIZE); +#endif + return RX_BUFF_SIZE; + } + } +#ifdef DEBUG_LANCE + fprintf(stderr, "lance: cannot receive\n"); +#endif + return 0; +} + +#define MIN_BUF_SIZE 60 + +static void lance_receive(void *opaque, const uint8_t *buf, int size) +{ + LANCEState *s = opaque; + void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]); + struct lance_init_block *ib; + unsigned int i, old_rxptr, j; + uint16_t temp; + + if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP) + return; + + ib = (void *) iommu_translate(dmaptr); + + old_rxptr = rxptr; + for (i = rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) { + cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1); + if (temp == (LE_R1_OWN)) { + rxptr = (rxptr + 1) & RX_RING_MOD_MASK; + temp = size; + bswap16s(&temp); + cpu_physical_memory_write(&ib->brx_ring[i].mblength, (void *) &temp, 2); +#if 0 + cpu_physical_memory_write(&ib->rx_buf[i], buf, size); +#else + for (j = 0; j < size; j++) { + cpu_physical_memory_write(((void *)&ib->rx_buf[i]) + j, &buf[j], 1); + } +#endif + temp = LE_R1_POK; + cpu_physical_memory_write(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1); + s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR; + if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA)) + pic_set_irq(s->irq, 1); +#ifdef DEBUG_LANCE + fprintf(stderr, "lance: got packet, len %d\n", size); +#endif + return; + } + } +} + +static void lance_send(void *opaque) +{ + LANCEState *s = opaque; + void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]); + struct lance_init_block *ib; + unsigned int i, old_txptr, j; + uint16_t temp; + char pkt_buf[PKT_BUF_SZ]; + + if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP) + return; + + ib = (void *) iommu_translate(dmaptr); + + old_txptr = txptr; + for (i = txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) { + cpu_physical_memory_read(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1); + if (temp == (LE_T1_POK|LE_T1_OWN)) { + cpu_physical_memory_read(&ib->btx_ring[i].length, (void *) &temp, 2); + bswap16s(&temp); + temp = (~temp) + 1; +#if 0 + cpu_physical_memory_read(&ib->tx_buf[i], pkt_buf, temp); +#else + for (j = 0; j < temp; j++) { + cpu_physical_memory_read(((void *)&ib->tx_buf[i]) + j, &pkt_buf[j], 1); + } +#endif + +#ifdef DEBUG_LANCE + fprintf(stderr, "lance: sending packet, len %d\n", temp); +#endif + qemu_send_packet(s->nd, pkt_buf, temp); + temp = LE_T1_POK; + cpu_physical_memory_write(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1); + txptr = (txptr + 1) & TX_RING_MOD_MASK; + s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR; + } + } +} + +static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr) +{ + LEDMAState *s = opaque; + uint32_t saddr; + + saddr = (addr - s->addr) >> 2; + if (saddr < LEDMA_REGS) + return s->regs[saddr]; + else + return 0; +} + +static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + LEDMAState *s = opaque; + uint32_t saddr; + + saddr = (addr - s->addr) >> 2; + if (saddr < LEDMA_REGS) + s->regs[saddr] = val; +} + +static CPUReadMemoryFunc *ledma_mem_read[3] = { + ledma_mem_readl, + ledma_mem_readl, + ledma_mem_readl, +}; + +static CPUWriteMemoryFunc *ledma_mem_write[3] = { + ledma_mem_writel, + ledma_mem_writel, + ledma_mem_writel, +}; + +void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr) +{ + LANCEState *s; + LEDMAState *led; + int lance_io_memory, ledma_io_memory; + + s = qemu_mallocz(sizeof(LANCEState)); + if (!s) + return; + + s->paddr = leaddr; + s->nd = nd; + s->irq = irq; + + lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s); + cpu_register_physical_memory(leaddr, 8, lance_io_memory); + + led = qemu_mallocz(sizeof(LEDMAState)); + if (!led) + return; + + s->ledma = led; + led->addr = ledaddr; + ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, led); + cpu_register_physical_memory(ledaddr, 16, ledma_io_memory); + + lance_reset(s); + qemu_add_read_packet(nd, lance_can_receive, lance_receive, s); +} + diff --git a/tools/ioemu/hw/m48t08.c b/tools/ioemu/hw/m48t08.c new file mode 100644 index 0000000000..46ec665570 --- /dev/null +++ b/tools/ioemu/hw/m48t08.c @@ -0,0 +1,391 @@ +/* + * QEMU M48T08 NVRAM emulation for Sparc platform + * + * Copyright (c) 2003-2004 Jocelyn Mayer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" +#include "m48t08.h" + +//#define DEBUG_NVRAM + +#if defined(DEBUG_NVRAM) +#define NVRAM_PRINTF(fmt, args...) do { printf(fmt , ##args); } while (0) +#else +#define NVRAM_PRINTF(fmt, args...) do { } while (0) +#endif + +#define NVRAM_MAX_MEM 0xfff0 + +struct m48t08_t { + /* Hardware parameters */ + int mem_index; + uint32_t mem_base; + uint16_t size; + /* RTC management */ + time_t time_offset; + time_t stop_time; + /* NVRAM storage */ + uint8_t lock; + uint16_t addr; + uint8_t *buffer; +}; + +/* Fake timer functions */ +/* Generic helpers for BCD */ +static inline uint8_t toBCD (uint8_t value) +{ + return (((value / 10) % 10) << 4) | (value % 10); +} + +static inline uint8_t fromBCD (uint8_t BCD) +{ + return ((BCD >> 4) * 10) + (BCD & 0x0F); +} + +/* RTC management helpers */ +static void get_time (m48t08_t *NVRAM, struct tm *tm) +{ + time_t t; + + t = time(NULL) + NVRAM->time_offset; +#ifdef _WIN32 + memcpy(tm,localtime(&t),sizeof(*tm)); +#else + localtime_r (&t, tm) ; +#endif +} + +static void set_time (m48t08_t *NVRAM, struct tm *tm) +{ + time_t now, new_time; + + new_time = mktime(tm); + now = time(NULL); + NVRAM->time_offset = new_time - now; +} + +/* Direct access to NVRAM */ +void m48t08_write (m48t08_t *NVRAM, uint32_t val) +{ + struct tm tm; + int tmp; + + if (NVRAM->addr > NVRAM_MAX_MEM && NVRAM->addr < 0x2000) + NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, NVRAM->addr, val); + switch (NVRAM->addr) { + case 0x1FF8: + /* control */ + NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90; + break; + case 0x1FF9: + /* seconds (BCD) */ + tmp = fromBCD(val & 0x7F); + if (tmp >= 0 && tmp <= 59) { + get_time(NVRAM, &tm); + tm.tm_sec = tmp; + set_time(NVRAM, &tm); + } + if ((val & 0x80) ^ (NVRAM->buffer[0x1FF9] & 0x80)) { + if (val & 0x80) { + NVRAM->stop_time = time(NULL); + } else { + NVRAM->time_offset += NVRAM->stop_time - time(NULL); + NVRAM->stop_time = 0; + } + } + NVRAM->buffer[0x1FF9] = val & 0x80; + break; + case 0x1FFA: + /* minutes (BCD) */ + tmp = fromBCD(val & 0x7F); + if (tmp >= 0 && tmp <= 59) { + get_time(NVRAM, &tm); + tm.tm_min = tmp; + set_time(NVRAM, &tm); + } + break; + case 0x1FFB: + /* hours (BCD) */ + tmp = fromBCD(val & 0x3F); + if (tmp >= 0 && tmp <= 23) { + get_time(NVRAM, &tm); + tm.tm_hour = tmp; + set_time(NVRAM, &tm); + } + break; + case 0x1FFC: + /* day of the week / century */ + tmp = fromBCD(val & 0x07); + get_time(NVRAM, &tm); + tm.tm_wday = tmp; + set_time(NVRAM, &tm); + NVRAM->buffer[0x1FFC] = val & 0x40; + break; + case 0x1FFD: + /* date */ + tmp = fromBCD(val & 0x1F); + if (tmp != 0) { + get_time(NVRAM, &tm); + tm.tm_mday = tmp; + set_time(NVRAM, &tm); + } + break; + case 0x1FFE: + /* month */ + tmp = fromBCD(val & 0x1F); + if (tmp >= 1 && tmp <= 12) { + get_time(NVRAM, &tm); + tm.tm_mon = tmp - 1; + set_time(NVRAM, &tm); + } + break; + case 0x1FFF: + /* year */ + tmp = fromBCD(val); + if (tmp >= 0 && tmp <= 99) { + get_time(NVRAM, &tm); + tm.tm_year = fromBCD(val); + set_time(NVRAM, &tm); + } + break; + default: + /* Check lock registers state */ + if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1)) + break; + if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2)) + break; + if (NVRAM->addr < NVRAM_MAX_MEM || + (NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) { + NVRAM->buffer[NVRAM->addr] = val & 0xFF; + } + break; + } +} + +uint32_t m48t08_read (m48t08_t *NVRAM) +{ + struct tm tm; + uint32_t retval = 0xFF; + + switch (NVRAM->addr) { + case 0x1FF8: + /* control */ + goto do_read; + case 0x1FF9: + /* seconds (BCD) */ + get_time(NVRAM, &tm); + retval = (NVRAM->buffer[0x1FF9] & 0x80) | toBCD(tm.tm_sec); + break; + case 0x1FFA: + /* minutes (BCD) */ + get_time(NVRAM, &tm); + retval = toBCD(tm.tm_min); + break; + case 0x1FFB: + /* hours (BCD) */ + get_time(NVRAM, &tm); + retval = toBCD(tm.tm_hour); + break; + case 0x1FFC: + /* day of the week / century */ + get_time(NVRAM, &tm); + retval = NVRAM->buffer[0x1FFC] | tm.tm_wday; + break; + case 0x1FFD: + /* date */ + get_time(NVRAM, &tm); + retval = toBCD(tm.tm_mday); + break; + case 0x1FFE: + /* month */ + get_time(NVRAM, &tm); + retval = toBCD(tm.tm_mon + 1); + break; + case 0x1FFF: + /* year */ + get_time(NVRAM, &tm); + retval = toBCD(tm.tm_year); + break; + default: + /* Check lock registers state */ + if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1)) + break; + if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2)) + break; + if (NVRAM->addr < NVRAM_MAX_MEM || + (NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) { + do_read: + retval = NVRAM->buffer[NVRAM->addr]; + } + break; + } + if (NVRAM->addr > NVRAM_MAX_MEM + 1 && NVRAM->addr < 0x2000) + NVRAM_PRINTF("0x%08x <= 0x%08x\n", NVRAM->addr, retval); + + return retval; +} + +void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr) +{ + NVRAM->addr = addr; +} + +void m48t08_toggle_lock (m48t08_t *NVRAM, int lock) +{ + NVRAM->lock ^= 1 << lock; +} + +static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) +{ + m48t08_t *NVRAM = opaque; + + addr -= NVRAM->mem_base; + if (addr < NVRAM_MAX_MEM) + NVRAM->buffer[addr] = value; +} + +static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value) +{ + m48t08_t *NVRAM = opaque; + + addr -= NVRAM->mem_base; + if (addr < NVRAM_MAX_MEM) { + NVRAM->buffer[addr] = value >> 8; + NVRAM->buffer[addr + 1] = value; + } +} + +static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +{ + m48t08_t *NVRAM = opaque; + + addr -= NVRAM->mem_base; + if (addr < NVRAM_MAX_MEM) { + NVRAM->buffer[addr] = value >> 24; + NVRAM->buffer[addr + 1] = value >> 16; + NVRAM->buffer[addr + 2] = value >> 8; + NVRAM->buffer[addr + 3] = value; + } +} + +static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr) +{ + m48t08_t *NVRAM = opaque; + uint32_t retval = 0; + + addr -= NVRAM->mem_base; + if (addr < NVRAM_MAX_MEM) + retval = NVRAM->buffer[addr]; + + return retval; +} + +static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr) +{ + m48t08_t *NVRAM = opaque; + uint32_t retval = 0; + + addr -= NVRAM->mem_base; + if (addr < NVRAM_MAX_MEM) { + retval = NVRAM->buffer[addr] << 8; + retval |= NVRAM->buffer[addr + 1]; + } + + return retval; +} + +static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr) +{ + m48t08_t *NVRAM = opaque; + uint32_t retval = 0; + + addr -= NVRAM->mem_base; + if (addr < NVRAM_MAX_MEM) { + retval = NVRAM->buffer[addr] << 24; + retval |= NVRAM->buffer[addr + 1] << 16; + retval |= NVRAM->buffer[addr + 2] << 8; + retval |= NVRAM->buffer[addr + 3]; + } + + return retval; +} + +static CPUWriteMemoryFunc *nvram_write[] = { + &nvram_writeb, + &nvram_writew, + &nvram_writel, +}; + +static CPUReadMemoryFunc *nvram_read[] = { + &nvram_readb, + &nvram_readw, + &nvram_readl, +}; + +/* Initialisation routine */ +m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr) +{ + m48t08_t *s; + int i; + unsigned char tmp = 0; + + s = qemu_mallocz(sizeof(m48t08_t)); + if (!s) + return NULL; + s->buffer = qemu_mallocz(size); + if (!s->buffer) { + qemu_free(s); + return NULL; + } + s->size = size; + s->mem_base = mem_base; + s->addr = 0; + if (mem_base != 0) { + s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s); + cpu_register_physical_memory(mem_base, 0x4000, s->mem_index); + } + s->lock = 0; + + i = 0x1fd8; + s->buffer[i++] = 0x01; + s->buffer[i++] = 0x80; /* Sun4m OBP */ + memcpy(&s->buffer[i], macaddr, 6); + + /* Calculate checksum */ + for (i = 0x1fd8; i < 0x1fe7; i++) { + tmp ^= s->buffer[i]; + } + s->buffer[0x1fe7] = tmp; + return s; +} + +#if 0 +struct idprom +{ + unsigned char id_format; /* Format identifier (always 0x01) */ + unsigned char id_machtype; /* Machine type */ + unsigned char id_ethaddr[6]; /* Hardware ethernet address */ + long id_date; /* Date of manufacture */ + unsigned int id_sernum:24; /* Unique serial number */ + unsigned char id_cksum; /* Checksum - xor of the data bytes */ + unsigned char reserved[16]; +}; +#endif diff --git a/tools/ioemu/hw/m48t08.h b/tools/ioemu/hw/m48t08.h new file mode 100644 index 0000000000..9b44bc0d16 --- /dev/null +++ b/tools/ioemu/hw/m48t08.h @@ -0,0 +1,12 @@ +#if !defined (__M48T08_H__) +#define __M48T08_H__ + +typedef struct m48t08_t m48t08_t; + +void m48t08_write (m48t08_t *NVRAM, uint32_t val); +uint32_t m48t08_read (m48t08_t *NVRAM); +void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr); +void m48t08_toggle_lock (m48t08_t *NVRAM, int lock); +m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr); + +#endif /* !defined (__M48T08_H__) */ diff --git a/tools/ioemu/hw/m48t59.c b/tools/ioemu/hw/m48t59.c new file mode 100644 index 0000000000..5ab58160a9 --- /dev/null +++ b/tools/ioemu/hw/m48t59.c @@ -0,0 +1,602 @@ +/* + * QEMU M48T59 NVRAM emulation for PPC PREP platform + * + * Copyright (c) 2003-2004 Jocelyn Mayer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" +#include "m48t59.h" + +//#define DEBUG_NVRAM + +#if defined(DEBUG_NVRAM) +#define NVRAM_PRINTF(fmt, args...) do { printf(fmt , ##args); } while (0) +#else +#define NVRAM_PRINTF(fmt, args...) do { } while (0) +#endif + +struct m48t59_t { + /* Hardware parameters */ + int IRQ; + int mem_index; + uint32_t mem_base; + uint32_t io_base; + uint16_t size; + /* RTC management */ + time_t time_offset; + time_t stop_time; + /* Alarm & watchdog */ + time_t alarm; + struct QEMUTimer *alrm_timer; + struct QEMUTimer *wd_timer; + /* NVRAM storage */ + uint8_t lock; + uint16_t addr; + uint8_t *buffer; +}; + +/* Fake timer functions */ +/* Generic helpers for BCD */ +static inline uint8_t toBCD (uint8_t value) +{ + return (((value / 10) % 10) << 4) | (value % 10); +} + +static inline uint8_t fromBCD (uint8_t BCD) +{ + return ((BCD >> 4) * 10) + (BCD & 0x0F); +} + +/* RTC management helpers */ +static void get_time (m48t59_t *NVRAM, struct tm *tm) +{ + time_t t; + + t = time(NULL) + NVRAM->time_offset; +#ifdef _WIN32 + memcpy(tm,localtime(&t),sizeof(*tm)); +#else + localtime_r (&t, tm) ; +#endif +} + +static void set_time (m48t59_t *NVRAM, struct tm *tm) +{ + time_t now, new_time; + + new_time = mktime(tm); + now = time(NULL); + NVRAM->time_offset = new_time - now; +} + +/* Alarm management */ +static void alarm_cb (void *opaque) +{ + struct tm tm, tm_now; + uint64_t next_time; + m48t59_t *NVRAM = opaque; + + pic_set_irq(NVRAM->IRQ, 1); + if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 && + (NVRAM->buffer[0x1FF4] & 0x80) == 0 && + (NVRAM->buffer[0x1FF3] & 0x80) == 0 && + (NVRAM->buffer[0x1FF2] & 0x80) == 0) { + /* Repeat once a month */ + get_time(NVRAM, &tm_now); + memcpy(&tm, &tm_now, sizeof(struct tm)); + tm.tm_mon++; + if (tm.tm_mon == 13) { + tm.tm_mon = 1; + tm.tm_year++; + } + next_time = mktime(&tm); + } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && + (NVRAM->buffer[0x1FF4] & 0x80) == 0 && + (NVRAM->buffer[0x1FF3] & 0x80) == 0 && + (NVRAM->buffer[0x1FF2] & 0x80) == 0) { + /* Repeat once a day */ + next_time = 24 * 60 * 60 + mktime(&tm_now); + } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && + (NVRAM->buffer[0x1FF4] & 0x80) != 0 && + (NVRAM->buffer[0x1FF3] & 0x80) == 0 && + (NVRAM->buffer[0x1FF2] & 0x80) == 0) { + /* Repeat once an hour */ + next_time = 60 * 60 + mktime(&tm_now); + } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 && + (NVRAM->buffer[0x1FF4] & 0x80) != 0 && + (NVRAM->buffer[0x1FF3] & 0x80) != 0 && + (NVRAM->buffer[0x1FF2] & 0x80) == 0) { + /* Repeat once a minute */ + next_time = 60 + mktime(&tm_now); + } else { + /* Repeat once a second */ + next_time = 1 + mktime(&tm_now); + } + qemu_mod_timer(NVRAM->alrm_timer, next_time * 1000); + pic_set_irq(NVRAM->IRQ, 0); +} + + +static void get_alarm (m48t59_t *NVRAM, struct tm *tm) +{ +#ifdef _WIN32 + memcpy(tm,localtime(&NVRAM->alarm),sizeof(*tm)); +#else + localtime_r (&NVRAM->alarm, tm); +#endif +} + +static void set_alarm (m48t59_t *NVRAM, struct tm *tm) +{ + NVRAM->alarm = mktime(tm); + if (NVRAM->alrm_timer != NULL) { + qemu_del_timer(NVRAM->alrm_timer); + NVRAM->alrm_timer = NULL; + } + if (NVRAM->alarm - time(NULL) > 0) + qemu_mod_timer(NVRAM->alrm_timer, NVRAM->alarm * 1000); +} + +/* Watchdog management */ +static void watchdog_cb (void *opaque) +{ + m48t59_t *NVRAM = opaque; + + NVRAM->buffer[0x1FF0] |= 0x80; + if (NVRAM->buffer[0x1FF7] & 0x80) { + NVRAM->buffer[0x1FF7] = 0x00; + NVRAM->buffer[0x1FFC] &= ~0x40; + /* May it be a hw CPU Reset instead ? */ + qemu_system_reset_request(); + } else { + pic_set_irq(NVRAM->IRQ, 1); + pic_set_irq(NVRAM->IRQ, 0); + } +} + +static void set_up_watchdog (m48t59_t *NVRAM, uint8_t value) +{ + uint64_t interval; /* in 1/16 seconds */ + + if (NVRAM->wd_timer != NULL) { + qemu_del_timer(NVRAM->wd_timer); + NVRAM->wd_timer = NULL; + } + NVRAM->buffer[0x1FF0] &= ~0x80; + if (value != 0) { + interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F); + qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) + + ((interval * 1000) >> 4)); + } +} + +/* Direct access to NVRAM */ +void m48t59_write (m48t59_t *NVRAM, uint32_t val) +{ + struct tm tm; + int tmp; + + if (NVRAM->addr > 0x1FF8 && NVRAM->addr < 0x2000) + NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, NVRAM->addr, val); + switch (NVRAM->addr) { + case 0x1FF0: + /* flags register : read-only */ + break; + case 0x1FF1: + /* unused */ + break; + case 0x1FF2: + /* alarm seconds */ + tmp = fromBCD(val & 0x7F); + if (tmp >= 0 && tmp <= 59) { + get_alarm(NVRAM, &tm); + tm.tm_sec = tmp; + NVRAM->buffer[0x1FF2] = val; + set_alarm(NVRAM, &tm); + } + break; + case 0x1FF3: + /* alarm minutes */ + tmp = fromBCD(val & 0x7F); + if (tmp >= 0 && tmp <= 59) { + get_alarm(NVRAM, &tm); + tm.tm_min = tmp; + NVRAM->buffer[0x1FF3] = val; + set_alarm(NVRAM, &tm); + } + break; + case 0x1FF4: + /* alarm hours */ + tmp = fromBCD(val & 0x3F); + if (tmp >= 0 && tmp <= 23) { + get_alarm(NVRAM, &tm); + tm.tm_hour = tmp; + NVRAM->buffer[0x1FF4] = val; + set_alarm(NVRAM, &tm); + } + break; + case 0x1FF5: + /* alarm date */ + tmp = fromBCD(val & 0x1F); + if (tmp != 0) { + get_alarm(NVRAM, &tm); + tm.tm_mday = tmp; + NVRAM->buffer[0x1FF5] = val; + set_alarm(NVRAM, &tm); + } + break; + case 0x1FF6: + /* interrupts */ + NVRAM->buffer[0x1FF6] = val; + break; + case 0x1FF7: + /* watchdog */ + NVRAM->buffer[0x1FF7] = val; + set_up_watchdog(NVRAM, val); + break; + case 0x1FF8: + /* control */ + NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90; + break; + case 0x1FF9: + /* seconds (BCD) */ + tmp = fromBCD(val & 0x7F); + if (tmp >= 0 && tmp <= 59) { + get_time(NVRAM, &tm); + tm.tm_sec = tmp; + set_time(NVRAM, &tm); + } + if ((val & 0x80) ^ (NVRAM->buffer[0x1FF9] & 0x80)) { + if (val & 0x80) { + NVRAM->stop_time = time(NULL); + } else { + NVRAM->time_offset += NVRAM->stop_time - time(NULL); + NVRAM->stop_time = 0; + } + } + NVRAM->buffer[0x1FF9] = val & 0x80; + break; + case 0x1FFA: + /* minutes (BCD) */ + tmp = fromBCD(val & 0x7F); + if (tmp >= 0 && tmp <= 59) { + get_time(NVRAM, &tm); + tm.tm_min = tmp; + set_time(NVRAM, &tm); + } + break; + case 0x1FFB: + /* hours (BCD) */ + tmp = fromBCD(val & 0x3F); + if (tmp >= 0 && tmp <= 23) { + get_time(NVRAM, &tm); + tm.tm_hour = tmp; + set_time(NVRAM, &tm); + } + break; + case 0x1FFC: + /* day of the week / century */ + tmp = fromBCD(val & 0x07); + get_time(NVRAM, &tm); + tm.tm_wday = tmp; + set_time(NVRAM, &tm); + NVRAM->buffer[0x1FFC] = val & 0x40; + break; + case 0x1FFD: + /* date */ + tmp = fromBCD(val & 0x1F); + if (tmp != 0) { + get_time(NVRAM, &tm); + tm.tm_mday = tmp; + set_time(NVRAM, &tm); + } + break; + case 0x1FFE: + /* month */ + tmp = fromBCD(val & 0x1F); + if (tmp >= 1 && tmp <= 12) { + get_time(NVRAM, &tm); + tm.tm_mon = tmp - 1; + set_time(NVRAM, &tm); + } + break; + case 0x1FFF: + /* year */ + tmp = fromBCD(val); + if (tmp >= 0 && tmp <= 99) { + get_time(NVRAM, &tm); + tm.tm_year = fromBCD(val); + set_time(NVRAM, &tm); + } + break; + default: + /* Check lock registers state */ + if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1)) + break; + if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2)) + break; + if (NVRAM->addr < 0x1FF0 || + (NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) { + NVRAM->buffer[NVRAM->addr] = val & 0xFF; + } + break; + } +} + +uint32_t m48t59_read (m48t59_t *NVRAM) +{ + struct tm tm; + uint32_t retval = 0xFF; + + switch (NVRAM->addr) { + case 0x1FF0: + /* flags register */ + goto do_read; + case 0x1FF1: + /* unused */ + retval = 0; + break; + case 0x1FF2: + /* alarm seconds */ + goto do_read; + case 0x1FF3: + /* alarm minutes */ + goto do_read; + case 0x1FF4: + /* alarm hours */ + goto do_read; + case 0x1FF5: + /* alarm date */ + goto do_read; + case 0x1FF6: + /* interrupts */ + goto do_read; + case 0x1FF7: + /* A read resets the watchdog */ + set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]); + goto do_read; + case 0x1FF8: + /* control */ + goto do_read; + case 0x1FF9: + /* seconds (BCD) */ + get_time(NVRAM, &tm); + retval = (NVRAM->buffer[0x1FF9] & 0x80) | toBCD(tm.tm_sec); + break; + case 0x1FFA: + /* minutes (BCD) */ + get_time(NVRAM, &tm); + retval = toBCD(tm.tm_min); + break; + case 0x1FFB: + /* hours (BCD) */ + get_time(NVRAM, &tm); + retval = toBCD(tm.tm_hour); + break; + case 0x1FFC: + /* day of the week / century */ + get_time(NVRAM, &tm); + retval = NVRAM->buffer[0x1FFC] | tm.tm_wday; + break; + case 0x1FFD: + /* date */ + get_time(NVRAM, &tm); + retval = toBCD(tm.tm_mday); + break; + case 0x1FFE: + /* month */ + get_time(NVRAM, &tm); + retval = toBCD(tm.tm_mon + 1); + break; + case 0x1FFF: + /* year */ + get_time(NVRAM, &tm); + retval = toBCD(tm.tm_year); + break; + default: + /* Check lock registers state */ + if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1)) + break; + if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2)) + break; + if (NVRAM->addr < 0x1FF0 || + (NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) { + do_read: + retval = NVRAM->buffer[NVRAM->addr]; + } + break; + } + if (NVRAM->addr > 0x1FF9 && NVRAM->addr < 0x2000) + NVRAM_PRINTF("0x%08x <= 0x%08x\n", NVRAM->addr, retval); + + return retval; +} + +void m48t59_set_addr (m48t59_t *NVRAM, uint32_t addr) +{ + NVRAM->addr = addr; +} + +void m48t59_toggle_lock (m48t59_t *NVRAM, int lock) +{ + NVRAM->lock ^= 1 << lock; +} + +/* IO access to NVRAM */ +static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val) +{ + m48t59_t *NVRAM = opaque; + + addr -= NVRAM->io_base; + NVRAM_PRINTF("0x%08x => 0x%08x\n", addr, val); + switch (addr) { + case 0: + NVRAM->addr &= ~0x00FF; + NVRAM->addr |= val; + break; + case 1: + NVRAM->addr &= ~0xFF00; + NVRAM->addr |= val << 8; + break; + case 3: + m48t59_write(NVRAM, val); + NVRAM->addr = 0x0000; + break; + default: + break; + } +} + +static uint32_t NVRAM_readb (void *opaque, uint32_t addr) +{ + m48t59_t *NVRAM = opaque; + uint32_t retval; + + addr -= NVRAM->io_base; + switch (addr) { + case 3: + retval = m48t59_read(NVRAM); + break; + default: + retval = -1; + break; + } + NVRAM_PRINTF("0x%08x <= 0x%08x\n", addr, retval); + + return retval; +} + +static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) +{ + m48t59_t *NVRAM = opaque; + + addr -= NVRAM->mem_base; + if (addr < 0x1FF0) + NVRAM->buffer[addr] = value; +} + +static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value) +{ + m48t59_t *NVRAM = opaque; + + addr -= NVRAM->mem_base; + if (addr < 0x1FF0) { + NVRAM->buffer[addr] = value >> 8; + NVRAM->buffer[addr + 1] = value; + } +} + +static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +{ + m48t59_t *NVRAM = opaque; + + addr -= NVRAM->mem_base; + if (addr < 0x1FF0) { + NVRAM->buffer[addr] = value >> 24; + NVRAM->buffer[addr + 1] = value >> 16; + NVRAM->buffer[addr + 2] = value >> 8; + NVRAM->buffer[addr + 3] = value; + } +} + +static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr) +{ + m48t59_t *NVRAM = opaque; + uint32_t retval = 0; + + addr -= NVRAM->mem_base; + if (addr < 0x1FF0) + retval = NVRAM->buffer[addr]; + + return retval; +} + +static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr) +{ + m48t59_t *NVRAM = opaque; + uint32_t retval = 0; + + addr -= NVRAM->mem_base; + if (addr < 0x1FF0) { + retval = NVRAM->buffer[addr] << 8; + retval |= NVRAM->buffer[addr + 1]; + } + + return retval; +} + +static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr) +{ + m48t59_t *NVRAM = opaque; + uint32_t retval = 0; + + addr -= NVRAM->mem_base; + if (addr < 0x1FF0) { + retval = NVRAM->buffer[addr] << 24; + retval |= NVRAM->buffer[addr + 1] << 16; + retval |= NVRAM->buffer[addr + 2] << 8; + retval |= NVRAM->buffer[addr + 3]; + } + + return retval; +} + +static CPUWriteMemoryFunc *nvram_write[] = { + &nvram_writeb, + &nvram_writew, + &nvram_writel, +}; + +static CPUReadMemoryFunc *nvram_read[] = { + &nvram_readb, + &nvram_readw, + &nvram_readl, +}; +/* Initialisation routine */ +m48t59_t *m48t59_init (int IRQ, uint32_t mem_base, + uint32_t io_base, uint16_t size) +{ + m48t59_t *s; + + s = qemu_mallocz(sizeof(m48t59_t)); + if (!s) + return NULL; + s->buffer = qemu_mallocz(size); + if (!s->buffer) { + qemu_free(s); + return NULL; + } + s->IRQ = IRQ; + s->size = size; + s->mem_base = mem_base; + s->io_base = io_base; + s->addr = 0; + register_ioport_read(io_base, 0x04, 1, NVRAM_readb, s); + register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, s); + if (mem_base != 0) { + s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s); + cpu_register_physical_memory(mem_base, 0x4000, s->mem_index); + } + s->alrm_timer = qemu_new_timer(vm_clock, &alarm_cb, s); + s->wd_timer = qemu_new_timer(vm_clock, &watchdog_cb, s); + s->lock = 0; + + return s; +} diff --git a/tools/ioemu/hw/m48t59.h b/tools/ioemu/hw/m48t59.h new file mode 100644 index 0000000000..03d8ea3b9b --- /dev/null +++ b/tools/ioemu/hw/m48t59.h @@ -0,0 +1,13 @@ +#if !defined (__M48T59_H__) +#define __M48T59_H__ + +typedef struct m48t59_t m48t59_t; + +void m48t59_write (m48t59_t *NVRAM, uint32_t val); +uint32_t m48t59_read (m48t59_t *NVRAM); +void m48t59_set_addr (m48t59_t *NVRAM, uint32_t addr); +void m48t59_toggle_lock (m48t59_t *NVRAM, int lock); +m48t59_t *m48t59_init (int IRQ, uint32_t io_base, + uint32_t mem_base, uint16_t size); + +#endif /* !defined (__M48T59_H__) */ diff --git a/tools/ioemu/hw/magic-load.c b/tools/ioemu/hw/magic-load.c new file mode 100644 index 0000000000..06a5f743af --- /dev/null +++ b/tools/ioemu/hw/magic-load.c @@ -0,0 +1,326 @@ +#include "vl.h" +#include "disas.h" + +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2MSB +#define ELF_ARCH EM_SPARC + +#include "elf.h" + +#ifdef BSWAP_NEEDED +static void bswap_ehdr(Elf32_Ehdr *ehdr) +{ + bswap16s(&ehdr->e_type); /* Object file type */ + bswap16s(&ehdr->e_machine); /* Architecture */ + bswap32s(&ehdr->e_version); /* Object file version */ + bswap32s(&ehdr->e_entry); /* Entry point virtual address */ + bswap32s(&ehdr->e_phoff); /* Program header table file offset */ + bswap32s(&ehdr->e_shoff); /* Section header table file offset */ + bswap32s(&ehdr->e_flags); /* Processor-specific flags */ + bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */ + bswap16s(&ehdr->e_phentsize); /* Program header table entry size */ + bswap16s(&ehdr->e_phnum); /* Program header table entry count */ + bswap16s(&ehdr->e_shentsize); /* Section header table entry size */ + bswap16s(&ehdr->e_shnum); /* Section header table entry count */ + bswap16s(&ehdr->e_shstrndx); /* Section header string table index */ +} + +static void bswap_phdr(Elf32_Phdr *phdr) +{ + bswap32s(&phdr->p_type); /* Segment type */ + bswap32s(&phdr->p_offset); /* Segment file offset */ + bswap32s(&phdr->p_vaddr); /* Segment virtual address */ + bswap32s(&phdr->p_paddr); /* Segment physical address */ + bswap32s(&phdr->p_filesz); /* Segment size in file */ + bswap32s(&phdr->p_memsz); /* Segment size in memory */ + bswap32s(&phdr->p_flags); /* Segment flags */ + bswap32s(&phdr->p_align); /* Segment alignment */ +} + +static void bswap_shdr(Elf32_Shdr *shdr) +{ + bswap32s(&shdr->sh_name); + bswap32s(&shdr->sh_type); + bswap32s(&shdr->sh_flags); + bswap32s(&shdr->sh_addr); + bswap32s(&shdr->sh_offset); + bswap32s(&shdr->sh_size); + bswap32s(&shdr->sh_link); + bswap32s(&shdr->sh_info); + bswap32s(&shdr->sh_addralign); + bswap32s(&shdr->sh_entsize); +} + +static void bswap_sym(Elf32_Sym *sym) +{ + bswap32s(&sym->st_name); + bswap32s(&sym->st_value); + bswap32s(&sym->st_size); + bswap16s(&sym->st_shndx); +} +#else +#define bswap_ehdr(e) do { } while (0) +#define bswap_phdr(e) do { } while (0) +#define bswap_shdr(e) do { } while (0) +#define bswap_sym(e) do { } while (0) +#endif + +static int find_phdr(struct elfhdr *ehdr, int fd, struct elf_phdr *phdr, uint32_t type) +{ + int i, retval; + + retval = lseek(fd, ehdr->e_phoff, SEEK_SET); + if (retval < 0) + return -1; + + for (i = 0; i < ehdr->e_phnum; i++) { + retval = read(fd, phdr, sizeof(*phdr)); + if (retval < 0) + return -1; + bswap_phdr(phdr); + if (phdr->p_type == type) + return 0; + } + return -1; +} + +static void *find_shdr(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type) +{ + int i, retval; + + retval = lseek(fd, ehdr->e_shoff, SEEK_SET); + if (retval < 0) + return NULL; + + for (i = 0; i < ehdr->e_shnum; i++) { + retval = read(fd, shdr, sizeof(*shdr)); + if (retval < 0) + return NULL; + bswap_shdr(shdr); + if (shdr->sh_type == type) + return qemu_malloc(shdr->sh_size); + } + return NULL; +} + +static int find_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab) +{ + int retval; + + retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET); + if (retval < 0) + return -1; + + retval = read(fd, shdr, sizeof(*shdr)); + if (retval < 0) + return -1; + bswap_shdr(shdr); + if (shdr->sh_type == SHT_STRTAB) + return qemu_malloc(shdr->sh_size);; + return 0; +} + +static int read_program(int fd, struct elf_phdr *phdr, void *dst) +{ + int retval; + retval = lseek(fd, 0x4000, SEEK_SET); + if (retval < 0) + return -1; + return read(fd, dst, phdr->p_filesz); +} + +static int read_section(int fd, struct elf_shdr *s, void *dst) +{ + int retval; + + retval = lseek(fd, s->sh_offset, SEEK_SET); + if (retval < 0) + return -1; + retval = read(fd, dst, s->sh_size); + if (retval < 0) + return -1; + return 0; +} + +static void *process_section(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type) +{ + void *dst; + + dst = find_shdr(ehdr, fd, shdr, type); + if (!dst) + goto error; + + if (read_section(fd, shdr, dst)) + goto error; + return dst; + error: + qemu_free(dst); + return NULL; +} + +static void *process_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab) +{ + void *dst; + + dst = find_strtab(ehdr, fd, shdr, symtab); + if (!dst) + goto error; + + if (read_section(fd, shdr, dst)) + goto error; + return dst; + error: + qemu_free(dst); + return NULL; +} + +static void load_symbols(struct elfhdr *ehdr, int fd) +{ + struct elf_shdr symtab, strtab; + struct elf_sym *syms; + int nsyms, i; + char *str; + + /* Symbol table */ + syms = process_section(ehdr, fd, &symtab, SHT_SYMTAB); + if (!syms) + return; + + nsyms = symtab.sh_size / sizeof(struct elf_sym); + for (i = 0; i < nsyms; i++) + bswap_sym(&syms[i]); + + /* String table */ + str = process_strtab(ehdr, fd, &strtab, &symtab); + if (!str) + goto error_freesyms; + + /* Commit */ + if (disas_symtab) + qemu_free(disas_symtab); /* XXX Merge with old symbols? */ + if (disas_strtab) + qemu_free(disas_strtab); + disas_symtab = syms; + disas_num_syms = nsyms; + disas_strtab = str; + return; + error_freesyms: + qemu_free(syms); + return; +} + +int load_elf(const char * filename, uint8_t *addr) +{ + struct elfhdr ehdr; + struct elf_phdr phdr; + int retval, fd; + + fd = open(filename, O_RDONLY | O_BINARY); + if (fd < 0) + goto error; + + retval = read(fd, &ehdr, sizeof(ehdr)); + if (retval < 0) + goto error; + + bswap_ehdr(&ehdr); + + if (ehdr.e_ident[0] != 0x7f || ehdr.e_ident[1] != 'E' + || ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F' + || ehdr.e_machine != EM_SPARC) + goto error; + + if (find_phdr(&ehdr, fd, &phdr, PT_LOAD)) + goto error; + retval = read_program(fd, &phdr, addr); + if (retval < 0) + goto error; + + load_symbols(&ehdr, fd); + + close(fd); + return retval; + error: + close(fd); + return -1; +} + +int load_kernel(const char *filename, uint8_t *addr) +{ + int fd, size; + + fd = open(filename, O_RDONLY | O_BINARY); + if (fd < 0) + return -1; + /* load 32 bit code */ + size = read(fd, addr, 16 * 1024 * 1024); + if (size < 0) + goto fail; + close(fd); + return size; + fail: + close(fd); + return -1; +} + +typedef struct MAGICState { + uint32_t addr; + uint32_t saved_addr; + int magic_state; + char saved_kfn[1024]; +} MAGICState; + +static uint32_t magic_mem_readl(void *opaque, target_phys_addr_t addr) +{ + int ret; + MAGICState *s = opaque; + + if (s->magic_state == 0) { + ret = load_elf(s->saved_kfn, (uint8_t *)s->saved_addr); + if (ret < 0) + ret = load_kernel(s->saved_kfn, (uint8_t *)s->saved_addr); + if (ret < 0) { + fprintf(stderr, "qemu: could not load kernel '%s'\n", + s->saved_kfn); + } + s->magic_state = 1; /* No more magic */ + tb_flush(); + return bswap32(ret); + } + return 0; +} + +static void magic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ +} + + +static CPUReadMemoryFunc *magic_mem_read[3] = { + magic_mem_readl, + magic_mem_readl, + magic_mem_readl, +}; + +static CPUWriteMemoryFunc *magic_mem_write[3] = { + magic_mem_writel, + magic_mem_writel, + magic_mem_writel, +}; + +void magic_init(const char *kfn, int kloadaddr, uint32_t addr) +{ + int magic_io_memory; + MAGICState *s; + + s = qemu_mallocz(sizeof(MAGICState)); + if (!s) + return; + + strcpy(s->saved_kfn, kfn); + s->saved_addr = kloadaddr; + s->magic_state = 0; + s->addr = addr; + magic_io_memory = cpu_register_io_memory(0, magic_mem_read, magic_mem_write, s); + cpu_register_physical_memory(addr, 4, magic_io_memory); +} + diff --git a/tools/ioemu/hw/mc146818rtc.c b/tools/ioemu/hw/mc146818rtc.c new file mode 100644 index 0000000000..9d4cbed90b --- /dev/null +++ b/tools/ioemu/hw/mc146818rtc.c @@ -0,0 +1,463 @@ +/* + * QEMU MC146818 RTC emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +//#define DEBUG_CMOS + +#define RTC_SECONDS 0 +#define RTC_SECONDS_ALARM 1 +#define RTC_MINUTES 2 +#define RTC_MINUTES_ALARM 3 +#define RTC_HOURS 4 +#define RTC_HOURS_ALARM 5 +#define RTC_ALARM_DONT_CARE 0xC0 + +#define RTC_DAY_OF_WEEK 6 +#define RTC_DAY_OF_MONTH 7 +#define RTC_MONTH 8 +#define RTC_YEAR 9 + +#define RTC_REG_A 10 +#define RTC_REG_B 11 +#define RTC_REG_C 12 +#define RTC_REG_D 13 + +#define REG_A_UIP 0x80 + +#define REG_B_SET 0x80 +#define REG_B_PIE 0x40 +#define REG_B_AIE 0x20 +#define REG_B_UIE 0x10 + +struct RTCState { + uint8_t cmos_data[128]; + uint8_t cmos_index; + struct tm current_tm; + int irq; + /* periodic timer */ + QEMUTimer *periodic_timer; + int64_t next_periodic_time; + /* second update */ + int64_t next_second_time; + QEMUTimer *second_timer; + QEMUTimer *second_timer2; +}; + +static void rtc_set_time(RTCState *s); +static void rtc_copy_date(RTCState *s); + +static void rtc_timer_update(RTCState *s, int64_t current_time) +{ + int period_code, period; + int64_t cur_clock, next_irq_clock; + + period_code = s->cmos_data[RTC_REG_A] & 0x0f; + if (period_code != 0 && + (s->cmos_data[RTC_REG_B] & REG_B_PIE)) { + if (period_code <= 2) + period_code += 7; + /* period in 32 Khz cycles */ + period = 1 << (period_code - 1); + /* compute 32 khz clock */ + cur_clock = muldiv64(current_time, 32768, ticks_per_sec); + next_irq_clock = (cur_clock & ~(period - 1)) + period; + s->next_periodic_time = muldiv64(next_irq_clock, ticks_per_sec, 32768) + 1; + qemu_mod_timer(s->periodic_timer, s->next_periodic_time); + } else { + qemu_del_timer(s->periodic_timer); + } +} + +static void rtc_periodic_timer(void *opaque) +{ + RTCState *s = opaque; + + rtc_timer_update(s, s->next_periodic_time); + s->cmos_data[RTC_REG_C] |= 0xc0; + pic_set_irq(s->irq, 1); +} + +static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data) +{ + RTCState *s = opaque; + + if ((addr & 1) == 0) { + s->cmos_index = data & 0x7f; + } else { +#ifdef DEBUG_CMOS + printf("cmos: write index=0x%02x val=0x%02x\n", + s->cmos_index, data); +#endif + switch(s->cmos_index) { + case RTC_SECONDS_ALARM: + case RTC_MINUTES_ALARM: + case RTC_HOURS_ALARM: + /* XXX: not supported */ + s->cmos_data[s->cmos_index] = data; + break; + case RTC_SECONDS: + case RTC_MINUTES: + case RTC_HOURS: + case RTC_DAY_OF_WEEK: + case RTC_DAY_OF_MONTH: + case RTC_MONTH: + case RTC_YEAR: + s->cmos_data[s->cmos_index] = data; + /* if in set mode, do not update the time */ + if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { + rtc_set_time(s); + } + break; + case RTC_REG_A: + /* UIP bit is read only */ + s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) | + (s->cmos_data[RTC_REG_A] & REG_A_UIP); + rtc_timer_update(s, qemu_get_clock(vm_clock)); + break; + case RTC_REG_B: + if (data & REG_B_SET) { + /* set mode: reset UIP mode */ + s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; + data &= ~REG_B_UIE; + } else { + /* if disabling set mode, update the time */ + if (s->cmos_data[RTC_REG_B] & REG_B_SET) { + rtc_set_time(s); + } + } + s->cmos_data[RTC_REG_B] = data; + rtc_timer_update(s, qemu_get_clock(vm_clock)); + break; + case RTC_REG_C: + case RTC_REG_D: + /* cannot write to them */ + break; + default: + s->cmos_data[s->cmos_index] = data; + break; + } + } +} + +static inline int to_bcd(RTCState *s, int a) +{ + if (s->cmos_data[RTC_REG_B] & 0x04) { + return a; + } else { + return ((a / 10) << 4) | (a % 10); + } +} + +static inline int from_bcd(RTCState *s, int a) +{ + if (s->cmos_data[RTC_REG_B] & 0x04) { + return a; + } else { + return ((a >> 4) * 10) + (a & 0x0f); + } +} + +static void rtc_set_time(RTCState *s) +{ + struct tm *tm = &s->current_tm; + + tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]); + tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]); + tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f); + if (!(s->cmos_data[RTC_REG_B] & 0x02) && + (s->cmos_data[RTC_HOURS] & 0x80)) { + tm->tm_hour += 12; + } + tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]); + tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]); + tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1; + tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100; +} + +static void rtc_copy_date(RTCState *s) +{ + const struct tm *tm = &s->current_tm; + + s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec); + s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min); + if (s->cmos_data[RTC_REG_B] & 0x02) { + /* 24 hour format */ + s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour); + } else { + /* 12 hour format */ + s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12); + if (tm->tm_hour >= 12) + s->cmos_data[RTC_HOURS] |= 0x80; + } + s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday); + s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday); + s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1); + s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100); +} + +/* month is between 0 and 11. */ +static int get_days_in_month(int month, int year) +{ + static const int days_tab[12] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + int d; + if ((unsigned )month >= 12) + return 31; + d = days_tab[month]; + if (month == 1) { + if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) + d++; + } + return d; +} + +/* update 'tm' to the next second */ +static void rtc_next_second(struct tm *tm) +{ + int days_in_month; + + tm->tm_sec++; + if ((unsigned)tm->tm_sec >= 60) { + tm->tm_sec = 0; + tm->tm_min++; + if ((unsigned)tm->tm_min >= 60) { + tm->tm_min = 0; + tm->tm_hour++; + if ((unsigned)tm->tm_hour >= 24) { + tm->tm_hour = 0; + /* next day */ + tm->tm_wday++; + if ((unsigned)tm->tm_wday >= 7) + tm->tm_wday = 0; + days_in_month = get_days_in_month(tm->tm_mon, + tm->tm_year + 1900); + tm->tm_mday++; + if (tm->tm_mday < 1) { + tm->tm_mday = 1; + } else if (tm->tm_mday > days_in_month) { + tm->tm_mday = 1; + tm->tm_mon++; + if (tm->tm_mon >= 12) { + tm->tm_mon = 0; + tm->tm_year++; + } + } + } + } + } +} + + +static void rtc_update_second(void *opaque) +{ + RTCState *s = opaque; + int64_t delay; + + /* if the oscillator is not in normal operation, we do not update */ + if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) { + s->next_second_time += ticks_per_sec; + qemu_mod_timer(s->second_timer, s->next_second_time); + } else { + rtc_next_second(&s->current_tm); + + if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { + /* update in progress bit */ + s->cmos_data[RTC_REG_A] |= REG_A_UIP; + } + /* should be 244 us = 8 / 32768 seconds, but currently the + timers do not have the necessary resolution. */ + delay = (ticks_per_sec * 1) / 100; + if (delay < 1) + delay = 1; + qemu_mod_timer(s->second_timer2, + s->next_second_time + delay); + } +} + +static void rtc_update_second2(void *opaque) +{ + RTCState *s = opaque; + + if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) { + rtc_copy_date(s); + } + + /* check alarm */ + if (s->cmos_data[RTC_REG_B] & REG_B_AIE) { + if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 || + s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) && + ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 || + s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) && + ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 || + s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) { + + s->cmos_data[RTC_REG_C] |= 0xa0; + pic_set_irq(s->irq, 1); + } + } + + /* update ended interrupt */ + if (s->cmos_data[RTC_REG_B] & REG_B_UIE) { + s->cmos_data[RTC_REG_C] |= 0x90; + pic_set_irq(s->irq, 1); + } + + /* clear update in progress bit */ + s->cmos_data[RTC_REG_A] &= ~REG_A_UIP; + + s->next_second_time += ticks_per_sec; + qemu_mod_timer(s->second_timer, s->next_second_time); +} + +static uint32_t cmos_ioport_read(void *opaque, uint32_t addr) +{ + RTCState *s = opaque; + int ret; + if ((addr & 1) == 0) { + return 0xff; + } else { + switch(s->cmos_index) { + case RTC_SECONDS: + case RTC_MINUTES: + case RTC_HOURS: + case RTC_DAY_OF_WEEK: + case RTC_DAY_OF_MONTH: + case RTC_MONTH: + case RTC_YEAR: + ret = s->cmos_data[s->cmos_index]; + break; + case RTC_REG_A: + ret = s->cmos_data[s->cmos_index]; + break; + case RTC_REG_C: + ret = s->cmos_data[s->cmos_index]; + pic_set_irq(s->irq, 0); + s->cmos_data[RTC_REG_C] = 0x00; + break; + default: + ret = s->cmos_data[s->cmos_index]; + break; + } +#ifdef DEBUG_CMOS + printf("cmos: read index=0x%02x val=0x%02x\n", + s->cmos_index, ret); +#endif + return ret; + } +} + +void rtc_set_memory(RTCState *s, int addr, int val) +{ + if (addr >= 0 && addr <= 127) + s->cmos_data[addr] = val; +} + +void rtc_set_date(RTCState *s, const struct tm *tm) +{ + s->current_tm = *tm; + rtc_copy_date(s); +} + +static void rtc_save(QEMUFile *f, void *opaque) +{ + RTCState *s = opaque; + + qemu_put_buffer(f, s->cmos_data, 128); + qemu_put_8s(f, &s->cmos_index); + + qemu_put_be32s(f, &s->current_tm.tm_sec); + qemu_put_be32s(f, &s->current_tm.tm_min); + qemu_put_be32s(f, &s->current_tm.tm_hour); + qemu_put_be32s(f, &s->current_tm.tm_wday); + qemu_put_be32s(f, &s->current_tm.tm_mday); + qemu_put_be32s(f, &s->current_tm.tm_mon); + qemu_put_be32s(f, &s->current_tm.tm_year); + + qemu_put_timer(f, s->periodic_timer); + qemu_put_be64s(f, &s->next_periodic_time); + + qemu_put_be64s(f, &s->next_second_time); + qemu_put_timer(f, s->second_timer); + qemu_put_timer(f, s->second_timer2); +} + +static int rtc_load(QEMUFile *f, void *opaque, int version_id) +{ + RTCState *s = opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_buffer(f, s->cmos_data, 128); + qemu_get_8s(f, &s->cmos_index); + + qemu_get_be32s(f, &s->current_tm.tm_sec); + qemu_get_be32s(f, &s->current_tm.tm_min); + qemu_get_be32s(f, &s->current_tm.tm_hour); + qemu_get_be32s(f, &s->current_tm.tm_wday); + qemu_get_be32s(f, &s->current_tm.tm_mday); + qemu_get_be32s(f, &s->current_tm.tm_mon); + qemu_get_be32s(f, &s->current_tm.tm_year); + + qemu_get_timer(f, s->periodic_timer); + qemu_get_be64s(f, &s->next_periodic_time); + + qemu_get_be64s(f, &s->next_second_time); + qemu_get_timer(f, s->second_timer); + qemu_get_timer(f, s->second_timer2); + return 0; +} + +RTCState *rtc_init(int base, int irq) +{ + RTCState *s; + + s = qemu_mallocz(sizeof(RTCState)); + if (!s) + return NULL; + + s->irq = irq; + s->cmos_data[RTC_REG_A] = 0x26; + s->cmos_data[RTC_REG_B] = 0x02; + s->cmos_data[RTC_REG_C] = 0x00; + s->cmos_data[RTC_REG_D] = 0x80; + + s->periodic_timer = qemu_new_timer(vm_clock, + rtc_periodic_timer, s); + s->second_timer = qemu_new_timer(vm_clock, + rtc_update_second, s); + s->second_timer2 = qemu_new_timer(vm_clock, + rtc_update_second2, s); + + s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100; + qemu_mod_timer(s->second_timer2, s->next_second_time); + + register_ioport_write(base, 2, 1, cmos_ioport_write, s); + register_ioport_read(base, 2, 1, cmos_ioport_read, s); + + register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s); + return s; +} + diff --git a/tools/ioemu/hw/ne2000.c b/tools/ioemu/hw/ne2000.c new file mode 100644 index 0000000000..79d3026c01 --- /dev/null +++ b/tools/ioemu/hw/ne2000.c @@ -0,0 +1,684 @@ +/* + * QEMU NE2000 emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +/* debug NE2000 card */ +//#define DEBUG_NE2000 + +#define MAX_ETH_FRAME_SIZE 1514 + +#define E8390_CMD 0x00 /* The command register (for all pages) */ +/* Page 0 register offsets. */ +#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */ +#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */ +#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */ +#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */ +#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */ +#define EN0_TSR 0x04 /* Transmit status reg RD */ +#define EN0_TPSR 0x04 /* Transmit starting page WR */ +#define EN0_NCR 0x05 /* Number of collision reg RD */ +#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */ +#define EN0_FIFO 0x06 /* FIFO RD */ +#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */ +#define EN0_ISR 0x07 /* Interrupt status reg RD WR */ +#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */ +#define EN0_RSARLO 0x08 /* Remote start address reg 0 */ +#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */ +#define EN0_RSARHI 0x09 /* Remote start address reg 1 */ +#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */ +#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */ +#define EN0_RSR 0x0c /* rx status reg RD */ +#define EN0_RXCR 0x0c /* RX configuration reg WR */ +#define EN0_TXCR 0x0d /* TX configuration reg WR */ +#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */ +#define EN0_DCFG 0x0e /* Data configuration reg WR */ +#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */ +#define EN0_IMR 0x0f /* Interrupt mask reg WR */ +#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */ + +#define EN1_PHYS 0x11 +#define EN1_CURPAG 0x17 +#define EN1_MULT 0x18 + +/* Register accessed at EN_CMD, the 8390 base addr. */ +#define E8390_STOP 0x01 /* Stop and reset the chip */ +#define E8390_START 0x02 /* Start the chip, clear reset */ +#define E8390_TRANS 0x04 /* Transmit a frame */ +#define E8390_RREAD 0x08 /* Remote read */ +#define E8390_RWRITE 0x10 /* Remote write */ +#define E8390_NODMA 0x20 /* Remote DMA */ +#define E8390_PAGE0 0x00 /* Select page chip registers */ +#define E8390_PAGE1 0x40 /* using the two high-order bits */ +#define E8390_PAGE2 0x80 /* Page 3 is invalid. */ + +/* Bits in EN0_ISR - Interrupt status register */ +#define ENISR_RX 0x01 /* Receiver, no error */ +#define ENISR_TX 0x02 /* Transmitter, no error */ +#define ENISR_RX_ERR 0x04 /* Receiver, with error */ +#define ENISR_TX_ERR 0x08 /* Transmitter, with error */ +#define ENISR_OVER 0x10 /* Receiver overwrote the ring */ +#define ENISR_COUNTERS 0x20 /* Counters need emptying */ +#define ENISR_RDC 0x40 /* remote dma complete */ +#define ENISR_RESET 0x80 /* Reset completed */ +#define ENISR_ALL 0x3f /* Interrupts we will enable */ + +/* Bits in received packet status byte and EN0_RSR*/ +#define ENRSR_RXOK 0x01 /* Received a good packet */ +#define ENRSR_CRC 0x02 /* CRC error */ +#define ENRSR_FAE 0x04 /* frame alignment error */ +#define ENRSR_FO 0x08 /* FIFO overrun */ +#define ENRSR_MPA 0x10 /* missed pkt */ +#define ENRSR_PHY 0x20 /* physical/multicast address */ +#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */ +#define ENRSR_DEF 0x80 /* deferring */ + +/* Transmitted packet status, EN0_TSR. */ +#define ENTSR_PTX 0x01 /* Packet transmitted without error */ +#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */ +#define ENTSR_COL 0x04 /* The transmit collided at least once. */ +#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */ +#define ENTSR_CRS 0x10 /* The carrier sense was lost. */ +#define ENTSR_FU 0x20 /* A "FIFO underrun" occurred during transmit. */ +#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */ +#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */ + +#define NE2000_PMEM_SIZE (32*1024) +#define NE2000_PMEM_START (16*1024) +#define NE2000_PMEM_END (NE2000_PMEM_SIZE+NE2000_PMEM_START) +#define NE2000_MEM_SIZE NE2000_PMEM_END + +typedef struct NE2000State { + uint8_t cmd; + uint32_t start; + uint32_t stop; + uint8_t boundary; + uint8_t tsr; + uint8_t tpsr; + uint16_t tcnt; + uint16_t rcnt; + uint32_t rsar; + uint8_t rsr; + uint8_t isr; + uint8_t dcfg; + uint8_t imr; + uint8_t phys[6]; /* mac address */ + uint8_t curpag; + uint8_t mult[8]; /* multicast mask array */ + int irq; + PCIDevice *pci_dev; + NetDriverState *nd; + uint8_t mem[NE2000_MEM_SIZE]; +} NE2000State; + +static void ne2000_reset(NE2000State *s) +{ + int i; + + s->isr = ENISR_RESET; + memcpy(s->mem, s->nd->macaddr, 6); + s->mem[14] = 0x57; + s->mem[15] = 0x57; + + /* duplicate prom data */ + for(i = 15;i >= 0; i--) { + s->mem[2 * i] = s->mem[i]; + s->mem[2 * i + 1] = s->mem[i]; + } +} + +static void ne2000_update_irq(NE2000State *s) +{ + int isr; + isr = s->isr & s->imr; +#if defined(DEBUG_NE2000) + printf("NE2000: Set IRQ line %d to %d (%02x %02x)\n", + s->irq, isr ? 1 : 0, s->isr, s->imr); +#endif + if (s->irq == 16) { + /* PCI irq */ + pci_set_irq(s->pci_dev, 0, (isr != 0)); + } else { + /* ISA irq */ + pic_set_irq(s->irq, (isr != 0)); + } +} + +/* return the max buffer size if the NE2000 can receive more data */ +static int ne2000_can_receive(void *opaque) +{ + NE2000State *s = opaque; + int avail, index, boundary; + + if (s->cmd & E8390_STOP) + return 0; + index = s->curpag << 8; + boundary = s->boundary << 8; + if (index < boundary) + avail = boundary - index; + else + avail = (s->stop - s->start) - (index - boundary); + if (avail < (MAX_ETH_FRAME_SIZE + 4)) + return 0; + return MAX_ETH_FRAME_SIZE; +} + +#define MIN_BUF_SIZE 60 + +static void ne2000_receive(void *opaque, const uint8_t *buf, int size) +{ + NE2000State *s = opaque; + uint8_t *p; + int total_len, next, avail, len, index; + uint8_t buf1[60]; + +#if defined(DEBUG_NE2000) + printf("NE2000: received len=%d\n", size); +#endif + + /* if too small buffer, then expand it */ + if (size < MIN_BUF_SIZE) { + memcpy(buf1, buf, size); + memset(buf1 + size, 0, MIN_BUF_SIZE - size); + buf = buf1; + size = MIN_BUF_SIZE; + } + + index = s->curpag << 8; + /* 4 bytes for header */ + total_len = size + 4; + /* address for next packet (4 bytes for CRC) */ + next = index + ((total_len + 4 + 255) & ~0xff); + if (next >= s->stop) + next -= (s->stop - s->start); + /* prepare packet header */ + p = s->mem + index; + s->rsr = ENRSR_RXOK; /* receive status */ + /* XXX: check this */ + if (buf[0] & 0x01) + s->rsr |= ENRSR_PHY; + p[0] = s->rsr; + p[1] = next >> 8; + p[2] = total_len; + p[3] = total_len >> 8; + index += 4; + + /* write packet data */ + while (size > 0) { + avail = s->stop - index; + len = size; + if (len > avail) + len = avail; + memcpy(s->mem + index, buf, len); + buf += len; + index += len; + if (index == s->stop) + index = s->start; + size -= len; + } + s->curpag = next >> 8; + + /* now we can signal we have receive something */ + s->isr |= ENISR_RX; + ne2000_update_irq(s); +} + +static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ + NE2000State *s = opaque; + int offset, page; + + addr &= 0xf; +#ifdef DEBUG_NE2000 + printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val); +#endif + if (addr == E8390_CMD) { + /* control register */ + s->cmd = val; + if (val & E8390_START) { + s->isr &= ~ENISR_RESET; + /* test specific case: zero length transfert */ + if ((val & (E8390_RREAD | E8390_RWRITE)) && + s->rcnt == 0) { + s->isr |= ENISR_RDC; + ne2000_update_irq(s); + } + if (val & E8390_TRANS) { + qemu_send_packet(s->nd, s->mem + (s->tpsr << 8), s->tcnt); + /* signal end of transfert */ + s->tsr = ENTSR_PTX; + s->isr |= ENISR_TX; + ne2000_update_irq(s); + } + } + } else { + page = s->cmd >> 6; + offset = addr | (page << 4); + switch(offset) { + case EN0_STARTPG: + s->start = val << 8; + break; + case EN0_STOPPG: + s->stop = val << 8; + break; + case EN0_BOUNDARY: + s->boundary = val; + break; + case EN0_IMR: + s->imr = val; + ne2000_update_irq(s); + break; + case EN0_TPSR: + s->tpsr = val; + break; + case EN0_TCNTLO: + s->tcnt = (s->tcnt & 0xff00) | val; + break; + case EN0_TCNTHI: + s->tcnt = (s->tcnt & 0x00ff) | (val << 8); + break; + case EN0_RSARLO: + s->rsar = (s->rsar & 0xff00) | val; + break; + case EN0_RSARHI: + s->rsar = (s->rsar & 0x00ff) | (val << 8); + break; + case EN0_RCNTLO: + s->rcnt = (s->rcnt & 0xff00) | val; + break; + case EN0_RCNTHI: + s->rcnt = (s->rcnt & 0x00ff) | (val << 8); + break; + case EN0_DCFG: + s->dcfg = val; + break; + case EN0_ISR: + s->isr &= ~(val & 0x7f); + ne2000_update_irq(s); + break; + case EN1_PHYS ... EN1_PHYS + 5: + s->phys[offset - EN1_PHYS] = val; + break; + case EN1_CURPAG: + s->curpag = val; + break; + case EN1_MULT ... EN1_MULT + 7: + s->mult[offset - EN1_MULT] = val; + break; + } + } +} + +static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr) +{ + NE2000State *s = opaque; + int offset, page, ret; + + addr &= 0xf; + if (addr == E8390_CMD) { + ret = s->cmd; + } else { + page = s->cmd >> 6; + offset = addr | (page << 4); + switch(offset) { + case EN0_TSR: + ret = s->tsr; + break; + case EN0_BOUNDARY: + ret = s->boundary; + break; + case EN0_ISR: + ret = s->isr; + break; + case EN0_RSARLO: + ret = s->rsar & 0x00ff; + break; + case EN0_RSARHI: + ret = s->rsar >> 8; + break; + case EN1_PHYS ... EN1_PHYS + 5: + ret = s->phys[offset - EN1_PHYS]; + break; + case EN1_CURPAG: + ret = s->curpag; + break; + case EN1_MULT ... EN1_MULT + 7: + ret = s->mult[offset - EN1_MULT]; + break; + case EN0_RSR: + ret = s->rsr; + break; + default: + ret = 0x00; + break; + } + } +#ifdef DEBUG_NE2000 + printf("NE2000: read addr=0x%x val=%02x\n", addr, ret); +#endif + return ret; +} + +static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr, + uint32_t val) +{ + if (addr < 32 || + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + s->mem[addr] = val; + } +} + +static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr, + uint32_t val) +{ + addr &= ~1; /* XXX: check exact behaviour if not even */ + if (addr < 32 || + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + *(uint16_t *)(s->mem + addr) = cpu_to_le16(val); + } +} + +static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr, + uint32_t val) +{ + addr &= ~1; /* XXX: check exact behaviour if not even */ + if (addr < 32 || + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + cpu_to_le32wu((uint32_t *)(s->mem + addr), val); + } +} + +static inline uint32_t ne2000_mem_readb(NE2000State *s, uint32_t addr) +{ + if (addr < 32 || + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + return s->mem[addr]; + } else { + return 0xff; + } +} + +static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr) +{ + addr &= ~1; /* XXX: check exact behaviour if not even */ + if (addr < 32 || + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + return le16_to_cpu(*(uint16_t *)(s->mem + addr)); + } else { + return 0xffff; + } +} + +static inline uint32_t ne2000_mem_readl(NE2000State *s, uint32_t addr) +{ + addr &= ~1; /* XXX: check exact behaviour if not even */ + if (addr < 32 || + (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) { + return le32_to_cpupu((uint32_t *)(s->mem + addr)); + } else { + return 0xffffffff; + } +} + +static inline void ne2000_dma_update(NE2000State *s, int len) +{ + s->rsar += len; + /* wrap */ + /* XXX: check what to do if rsar > stop */ + if (s->rsar == s->stop) + s->rsar = s->start; + + if (s->rcnt <= len) { + s->rcnt = 0; + /* signal end of transfert */ + s->isr |= ENISR_RDC; + ne2000_update_irq(s); + } else { + s->rcnt -= len; + } +} + +static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ + NE2000State *s = opaque; + +#ifdef DEBUG_NE2000 + printf("NE2000: asic write val=0x%04x\n", val); +#endif + if (s->rcnt == 0) + return; + if (s->dcfg & 0x01) { + /* 16 bit access */ + ne2000_mem_writew(s, s->rsar, val); + ne2000_dma_update(s, 2); + } else { + /* 8 bit access */ + ne2000_mem_writeb(s, s->rsar, val); + ne2000_dma_update(s, 1); + } +} + +static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr) +{ + NE2000State *s = opaque; + int ret; + + if (s->dcfg & 0x01) { + /* 16 bit access */ + ret = ne2000_mem_readw(s, s->rsar); + ne2000_dma_update(s, 2); + } else { + /* 8 bit access */ + ret = ne2000_mem_readb(s, s->rsar); + ne2000_dma_update(s, 1); + } +#ifdef DEBUG_NE2000 + printf("NE2000: asic read val=0x%04x\n", ret); +#endif + return ret; +} + +static void ne2000_asic_ioport_writel(void *opaque, uint32_t addr, uint32_t val) +{ + NE2000State *s = opaque; + +#ifdef DEBUG_NE2000 + printf("NE2000: asic writel val=0x%04x\n", val); +#endif + if (s->rcnt == 0) + return; + /* 32 bit access */ + ne2000_mem_writel(s, s->rsar, val); + ne2000_dma_update(s, 4); +} + +static uint32_t ne2000_asic_ioport_readl(void *opaque, uint32_t addr) +{ + NE2000State *s = opaque; + int ret; + + /* 32 bit access */ + ret = ne2000_mem_readl(s, s->rsar); + ne2000_dma_update(s, 4); +#ifdef DEBUG_NE2000 + printf("NE2000: asic readl val=0x%04x\n", ret); +#endif + return ret; +} + +static void ne2000_reset_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ + /* nothing to do (end of reset pulse) */ +} + +static uint32_t ne2000_reset_ioport_read(void *opaque, uint32_t addr) +{ + NE2000State *s = opaque; + ne2000_reset(s); + return 0; +} + +static void ne2000_save(QEMUFile* f,void* opaque) +{ + NE2000State* s=(NE2000State*)opaque; + + qemu_put_8s(f, &s->cmd); + qemu_put_be32s(f, &s->start); + qemu_put_be32s(f, &s->stop); + qemu_put_8s(f, &s->boundary); + qemu_put_8s(f, &s->tsr); + qemu_put_8s(f, &s->tpsr); + qemu_put_be16s(f, &s->tcnt); + qemu_put_be16s(f, &s->rcnt); + qemu_put_be32s(f, &s->rsar); + qemu_put_8s(f, &s->rsr); + qemu_put_8s(f, &s->isr); + qemu_put_8s(f, &s->dcfg); + qemu_put_8s(f, &s->imr); + qemu_put_buffer(f, s->phys, 6); + qemu_put_8s(f, &s->curpag); + qemu_put_buffer(f, s->mult, 8); + qemu_put_be32s(f, &s->irq); + qemu_put_buffer(f, s->mem, NE2000_MEM_SIZE); +} + +static int ne2000_load(QEMUFile* f,void* opaque,int version_id) +{ + NE2000State* s=(NE2000State*)opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_8s(f, &s->cmd); + qemu_get_be32s(f, &s->start); + qemu_get_be32s(f, &s->stop); + qemu_get_8s(f, &s->boundary); + qemu_get_8s(f, &s->tsr); + qemu_get_8s(f, &s->tpsr); + qemu_get_be16s(f, &s->tcnt); + qemu_get_be16s(f, &s->rcnt); + qemu_get_be32s(f, &s->rsar); + qemu_get_8s(f, &s->rsr); + qemu_get_8s(f, &s->isr); + qemu_get_8s(f, &s->dcfg); + qemu_get_8s(f, &s->imr); + qemu_get_buffer(f, s->phys, 6); + qemu_get_8s(f, &s->curpag); + qemu_get_buffer(f, s->mult, 8); + qemu_get_be32s(f, &s->irq); + qemu_get_buffer(f, s->mem, NE2000_MEM_SIZE); + + return 0; +} + +void isa_ne2000_init(int base, int irq, NetDriverState *nd) +{ + NE2000State *s; + + s = qemu_mallocz(sizeof(NE2000State)); + if (!s) + return; + + register_ioport_write(base, 16, 1, ne2000_ioport_write, s); + register_ioport_read(base, 16, 1, ne2000_ioport_read, s); + + register_ioport_write(base + 0x10, 1, 1, ne2000_asic_ioport_write, s); + register_ioport_read(base + 0x10, 1, 1, ne2000_asic_ioport_read, s); + register_ioport_write(base + 0x10, 2, 2, ne2000_asic_ioport_write, s); + register_ioport_read(base + 0x10, 2, 2, ne2000_asic_ioport_read, s); + + register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s); + register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s); + s->irq = irq; + s->nd = nd; + + ne2000_reset(s); + + qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s); + + register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s); + +} + +/***********************************************************/ +/* PCI NE2000 definitions */ + +typedef struct PCINE2000State { + PCIDevice dev; + NE2000State ne2000; +} PCINE2000State; + +static void ne2000_map(PCIDevice *pci_dev, int region_num, + uint32_t addr, uint32_t size, int type) +{ + PCINE2000State *d = (PCINE2000State *)pci_dev; + NE2000State *s = &d->ne2000; + + register_ioport_write(addr, 16, 1, ne2000_ioport_write, s); + register_ioport_read(addr, 16, 1, ne2000_ioport_read, s); + + register_ioport_write(addr + 0x10, 1, 1, ne2000_asic_ioport_write, s); + register_ioport_read(addr + 0x10, 1, 1, ne2000_asic_ioport_read, s); + register_ioport_write(addr + 0x10, 2, 2, ne2000_asic_ioport_write, s); + register_ioport_read(addr + 0x10, 2, 2, ne2000_asic_ioport_read, s); + register_ioport_write(addr + 0x10, 4, 4, ne2000_asic_ioport_writel, s); + register_ioport_read(addr + 0x10, 4, 4, ne2000_asic_ioport_readl, s); + + register_ioport_write(addr + 0x1f, 1, 1, ne2000_reset_ioport_write, s); + register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s); +} + +void pci_ne2000_init(PCIBus *bus, NetDriverState *nd) +{ + PCINE2000State *d; + NE2000State *s; + uint8_t *pci_conf; + + d = (PCINE2000State *)pci_register_device(bus, + "NE2000", sizeof(PCINE2000State), + -1, + NULL, NULL); + pci_conf = d->dev.config; + pci_conf[0x00] = 0xec; // Realtek 8029 + pci_conf[0x01] = 0x10; + pci_conf[0x02] = 0x29; + pci_conf[0x03] = 0x80; + pci_conf[0x0a] = 0x00; // ethernet network controller + pci_conf[0x0b] = 0x02; + pci_conf[0x0e] = 0x00; // header_type + pci_conf[0x3d] = 1; // interrupt pin 0 + + pci_register_io_region(&d->dev, 0, 0x100, + PCI_ADDRESS_SPACE_IO, ne2000_map); + s = &d->ne2000; + s->irq = 16; // PCI interrupt + s->pci_dev = (PCIDevice *)d; + s->nd = nd; + ne2000_reset(s); + qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s); + + /* XXX: instance number ? */ + register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s); + register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load, + &d->dev); +} diff --git a/tools/ioemu/hw/openpic.c b/tools/ioemu/hw/openpic.c new file mode 100644 index 0000000000..d193cfe6f2 --- /dev/null +++ b/tools/ioemu/hw/openpic.c @@ -0,0 +1,1023 @@ +/* + * OpenPIC emulation + * + * Copyright (c) 2004 Jocelyn Mayer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* + * + * Based on OpenPic implementations: + * - Intel GW80314 I/O compagnion chip developper's manual + * - Motorola MPC8245 & MPC8540 user manuals. + * - Motorola MCP750 (aka Raven) programmer manual. + * - Motorola Harrier programmer manuel + * + * Serial interrupts, as implemented in Raven chipset are not supported yet. + * + */ +#include "vl.h" + +//#define DEBUG_OPENPIC + +#ifdef DEBUG_OPENPIC +#define DPRINTF(fmt, args...) do { printf(fmt , ##args); } while (0) +#else +#define DPRINTF(fmt, args...) do { } while (0) +#endif +#define ERROR(fmr, args...) do { printf("ERROR: " fmr , ##args); } while (0) + +#define USE_MPCxxx /* Intel model is broken, for now */ + +#if defined (USE_INTEL_GW80314) +/* Intel GW80314 I/O Companion chip */ + +#define MAX_CPU 4 +#define MAX_IRQ 32 +#define MAX_DBL 4 +#define MAX_MBX 4 +#define MAX_TMR 4 +#define VECTOR_BITS 8 +#define MAX_IPI 0 + +#define VID (0x00000000) + +#define OPENPIC_LITTLE_ENDIAN 1 +#define OPENPIC_BIG_ENDIAN 0 + +#elif defined(USE_MPCxxx) + +#define MAX_CPU 2 +#define MAX_IRQ 64 +#define EXT_IRQ 48 +#define MAX_DBL 0 +#define MAX_MBX 0 +#define MAX_TMR 4 +#define VECTOR_BITS 8 +#define MAX_IPI 4 +#define VID 0x03 /* MPIC version ID */ +#define VENI 0x00000000 /* Vendor ID */ + +enum { + IRQ_IPVP = 0, + IRQ_IDE, +}; + +#define OPENPIC_LITTLE_ENDIAN 1 +#define OPENPIC_BIG_ENDIAN 0 + +#else +#error "Please select which OpenPic implementation is to be emulated" +#endif + +#if (OPENPIC_BIG_ENDIAN && !TARGET_WORDS_BIGENDIAN) || \ + (OPENPIC_LITTLE_ENDIAN && TARGET_WORDS_BIGENDIAN) +#define OPENPIC_SWAP +#endif + +/* Interrupt definitions */ +#define IRQ_FE (EXT_IRQ) /* Internal functional IRQ */ +#define IRQ_ERR (EXT_IRQ + 1) /* Error IRQ */ +#define IRQ_TIM0 (EXT_IRQ + 2) /* First timer IRQ */ +#if MAX_IPI > 0 +#define IRQ_IPI0 (IRQ_TIM0 + MAX_TMR) /* First IPI IRQ */ +#define IRQ_DBL0 (IRQ_IPI0 + (MAX_CPU * MAX_IPI)) /* First doorbell IRQ */ +#else +#define IRQ_DBL0 (IRQ_TIM0 + MAX_TMR) /* First doorbell IRQ */ +#define IRQ_MBX0 (IRQ_DBL0 + MAX_DBL) /* First mailbox IRQ */ +#endif + +#define BF_WIDTH(_bits_) \ +(((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8)) + +static inline void set_bit (uint32_t *field, int bit) +{ + field[bit >> 5] |= 1 << (bit & 0x1F); +} + +static inline void reset_bit (uint32_t *field, int bit) +{ + field[bit >> 5] &= ~(1 << (bit & 0x1F)); +} + +static inline int test_bit (uint32_t *field, int bit) +{ + return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0; +} + +enum { + IRQ_EXTERNAL = 0x01, + IRQ_INTERNAL = 0x02, + IRQ_TIMER = 0x04, + IRQ_SPECIAL = 0x08, +} IRQ_src_type; + +typedef struct IRQ_queue_t { + uint32_t queue[BF_WIDTH(MAX_IRQ)]; + int next; + int priority; +} IRQ_queue_t; + +typedef struct IRQ_src_t { + uint32_t ipvp; /* IRQ vector/priority register */ + uint32_t ide; /* IRQ destination register */ + int type; + int last_cpu; + int pending; /* TRUE if IRQ is pending */ +} IRQ_src_t; + +enum IPVP_bits { + IPVP_MASK = 31, + IPVP_ACTIVITY = 30, + IPVP_MODE = 29, + IPVP_POLARITY = 23, + IPVP_SENSE = 22, +}; +#define IPVP_PRIORITY_MASK (0x1F << 16) +#define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16)) +#define IPVP_VECTOR_MASK ((1 << VECTOR_BITS) - 1) +#define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK) + +typedef struct IRQ_dst_t { + uint32_t pctp; /* CPU current task priority */ + uint32_t pcsr; /* CPU sensitivity register */ + IRQ_queue_t raised; + IRQ_queue_t servicing; + CPUState *env; /* Needed if we did SMP */ +} IRQ_dst_t; + +struct openpic_t { + PCIDevice pci_dev; + int mem_index; + /* Global registers */ + uint32_t frep; /* Feature reporting register */ + uint32_t glbc; /* Global configuration register */ + uint32_t micr; /* MPIC interrupt configuration register */ + uint32_t veni; /* Vendor identification register */ + uint32_t spve; /* Spurious vector register */ + uint32_t tifr; /* Timer frequency reporting register */ + /* Source registers */ + IRQ_src_t src[MAX_IRQ]; + /* Local registers per output pin */ + IRQ_dst_t dst[MAX_CPU]; + int nb_cpus; + /* Timer registers */ + struct { + uint32_t ticc; /* Global timer current count register */ + uint32_t tibc; /* Global timer base count register */ + } timers[MAX_TMR]; +#if MAX_DBL > 0 + /* Doorbell registers */ + uint32_t dar; /* Doorbell activate register */ + struct { + uint32_t dmr; /* Doorbell messaging register */ + } doorbells[MAX_DBL]; +#endif +#if MAX_MBX > 0 + /* Mailbox registers */ + struct { + uint32_t mbr; /* Mailbox register */ + } mailboxes[MAX_MAILBOXES]; +#endif +}; + +static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ) +{ + set_bit(q->queue, n_IRQ); +} + +static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ) +{ + reset_bit(q->queue, n_IRQ); +} + +static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ) +{ + return test_bit(q->queue, n_IRQ); +} + +static void IRQ_check (openpic_t *opp, IRQ_queue_t *q) +{ + int next, i; + int priority; + + next = -1; + priority = -1; + for (i = 0; i < MAX_IRQ; i++) { + if (IRQ_testbit(q, i)) { + DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n", + i, IPVP_PRIORITY(opp->src[i].ipvp), priority); + if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) { + next = i; + priority = IPVP_PRIORITY(opp->src[i].ipvp); + } + } + } + q->next = next; + q->priority = priority; +} + +static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q) +{ + if (q->next == -1) { + /* XXX: optimize */ + IRQ_check(opp, q); + } + + return q->next; +} + +static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ) +{ + IRQ_dst_t *dst; + IRQ_src_t *src; + int priority; + + dst = &opp->dst[n_CPU]; + src = &opp->src[n_IRQ]; + priority = IPVP_PRIORITY(src->ipvp); + if (priority <= dst->pctp) { + /* Too low priority */ + return; + } + if (IRQ_testbit(&dst->raised, n_IRQ)) { + /* Interrupt miss */ + return; + } + set_bit(&src->ipvp, IPVP_ACTIVITY); + IRQ_setbit(&dst->raised, n_IRQ); + if (priority > dst->raised.priority) { + IRQ_get_next(opp, &dst->raised); + DPRINTF("Raise CPU IRQ\n"); + cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD); + } +} + +/* update pic state because registers for n_IRQ have changed value */ +static void openpic_update_irq(openpic_t *opp, int n_IRQ) +{ + IRQ_src_t *src; + int i; + + src = &opp->src[n_IRQ]; + + if (!src->pending) { + /* no irq pending */ + return; + } + if (test_bit(&src->ipvp, IPVP_MASK)) { + /* Interrupt source is disabled */ + return; + } + if (IPVP_PRIORITY(src->ipvp) == 0) { + /* Priority set to zero */ + return; + } + if (test_bit(&src->ipvp, IPVP_ACTIVITY)) { + /* IRQ already active */ + return; + } + if (src->ide == 0x00000000) { + /* No target */ + return; + } + + if (!test_bit(&src->ipvp, IPVP_MODE) || + src->ide == (1 << src->last_cpu)) { + /* Directed delivery mode */ + for (i = 0; i < opp->nb_cpus; i++) { + if (test_bit(&src->ide, i)) + IRQ_local_pipe(opp, i, n_IRQ); + } + } else { + /* Distributed delivery mode */ + /* XXX: incorrect code */ + for (i = src->last_cpu; i < src->last_cpu; i++) { + if (i == MAX_IRQ) + i = 0; + if (test_bit(&src->ide, i)) { + IRQ_local_pipe(opp, i, n_IRQ); + src->last_cpu = i; + break; + } + } + } +} + +void openpic_set_irq(openpic_t *opp, int n_IRQ, int level) +{ + IRQ_src_t *src; + + src = &opp->src[n_IRQ]; + DPRINTF("openpic: set irq %d = %d ipvp=%08x\n", + n_IRQ, level, src->ipvp); + if (test_bit(&src->ipvp, IPVP_SENSE)) { + /* level-sensitive irq */ + src->pending = level; + if (!level) + reset_bit(&src->ipvp, IPVP_ACTIVITY); + } else { + /* edge-sensitive irq */ + if (level) + src->pending = 1; + } + openpic_update_irq(opp, n_IRQ); +} + +static void openpic_reset (openpic_t *opp) +{ + int i; + + opp->glbc = 0x80000000; + /* Initialise controler registers */ + opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID; + opp->veni = VENI; + opp->spve = 0x000000FF; + opp->tifr = 0x003F7A00; + /* ? */ + opp->micr = 0x00000000; + /* Initialise IRQ sources */ + for (i = 0; i < MAX_IRQ; i++) { + opp->src[i].ipvp = 0xA0000000; + opp->src[i].ide = 0x00000000; + } + /* Initialise IRQ destinations */ + for (i = 0; i < opp->nb_cpus; i++) { + opp->dst[i].pctp = 0x0000000F; + opp->dst[i].pcsr = 0x00000000; + memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t)); + memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t)); + } + /* Initialise timers */ + for (i = 0; i < MAX_TMR; i++) { + opp->timers[i].ticc = 0x00000000; + opp->timers[i].tibc = 0x80000000; + } + /* Initialise doorbells */ +#if MAX_DBL > 0 + opp->dar = 0x00000000; + for (i = 0; i < MAX_DBL; i++) { + opp->doorbells[i].dmr = 0x00000000; + } +#endif + /* Initialise mailboxes */ +#if MAX_MBX > 0 + for (i = 0; i < MAX_MBX; i++) { /* ? */ + opp->mailboxes[i].mbr = 0x00000000; + } +#endif + /* Go out of RESET state */ + opp->glbc = 0x00000000; +} + +static inline uint32_t read_IRQreg (openpic_t *opp, int n_IRQ, uint32_t reg) +{ + uint32_t retval; + + switch (reg) { + case IRQ_IPVP: + retval = opp->src[n_IRQ].ipvp; + break; + case IRQ_IDE: + retval = opp->src[n_IRQ].ide; + break; + } + + return retval; +} + +static inline void write_IRQreg (openpic_t *opp, int n_IRQ, + uint32_t reg, uint32_t val) +{ + uint32_t tmp; + + switch (reg) { + case IRQ_IPVP: + /* NOTE: not fully accurate for special IRQs, but simple and + sufficient */ + /* ACTIVITY bit is read-only */ + opp->src[n_IRQ].ipvp = + (opp->src[n_IRQ].ipvp & 0x40000000) | + (val & 0x800F00FF); + openpic_update_irq(opp, n_IRQ); + DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", + n_IRQ, val, opp->src[n_IRQ].ipvp); + break; + case IRQ_IDE: + tmp = val & 0xC0000000; + tmp |= val & ((1 << MAX_CPU) - 1); + opp->src[n_IRQ].ide = tmp; + DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide); + break; + } +} + +#if 0 // Code provision for Intel model +#if MAX_DBL > 0 +static uint32_t read_doorbell_register (openpic_t *opp, + int n_dbl, uint32_t offset) +{ + uint32_t retval; + + switch (offset) { + case DBL_IPVP_OFFSET: + retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP); + break; + case DBL_IDE_OFFSET: + retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE); + break; + case DBL_DMR_OFFSET: + retval = opp->doorbells[n_dbl].dmr; + break; + } + + return retval; +} + +static void write_doorbell_register (penpic_t *opp, int n_dbl, + uint32_t offset, uint32_t value) +{ + switch (offset) { + case DBL_IVPR_OFFSET: + write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP, value); + break; + case DBL_IDE_OFFSET: + write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE, value); + break; + case DBL_DMR_OFFSET: + opp->doorbells[n_dbl].dmr = value; + break; + } +} +#endif + +#if MAX_MBX > 0 +static uint32_t read_mailbox_register (openpic_t *opp, + int n_mbx, uint32_t offset) +{ + uint32_t retval; + + switch (offset) { + case MBX_MBR_OFFSET: + retval = opp->mailboxes[n_mbx].mbr; + break; + case MBX_IVPR_OFFSET: + retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP); + break; + case MBX_DMR_OFFSET: + retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE); + break; + } + + return retval; +} + +static void write_mailbox_register (openpic_t *opp, int n_mbx, + uint32_t address, uint32_t value) +{ + switch (offset) { + case MBX_MBR_OFFSET: + opp->mailboxes[n_mbx].mbr = value; + break; + case MBX_IVPR_OFFSET: + write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP, value); + break; + case MBX_DMR_OFFSET: + write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE, value); + break; + } +} +#endif +#endif /* 0 : Code provision for Intel model */ + +static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val) +{ + openpic_t *opp = opaque; + + DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); + if (addr & 0xF) + return; +#if defined OPENPIC_SWAP + val = bswap32(val); +#endif + addr &= 0xFF; + switch (addr) { + case 0x00: /* FREP */ + break; + case 0x20: /* GLBC */ + if (val & 0x80000000) + openpic_reset(opp); + opp->glbc = val & ~0x80000000; + break; + case 0x80: /* VENI */ + break; + case 0x90: /* PINT */ + /* XXX: Should be able to reset any CPU */ + if (val & 1) { + DPRINTF("Reset CPU IRQ\n"); + // cpu_interrupt(cpu_single_env, CPU_INTERRUPT_RESET); + } + break; +#if MAX_IPI > 0 + case 0xA0: /* IPI_IPVP */ + case 0xB0: + case 0xC0: + case 0xD0: + { + int idx; + idx = (addr - 0xA0) >> 4; + write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP, val); + } + break; +#endif + case 0xE0: /* SPVE */ + opp->spve = val & 0x000000FF; + break; + case 0xF0: /* TIFR */ + opp->tifr = val; + break; + default: + break; + } +} + +static uint32_t openpic_gbl_read (void *opaque, uint32_t addr) +{ + openpic_t *opp = opaque; + uint32_t retval; + + DPRINTF("%s: addr %08x\n", __func__, addr); + retval = 0xFFFFFFFF; + if (addr & 0xF) + return retval; + addr &= 0xFF; + switch (addr) { + case 0x00: /* FREP */ + retval = opp->frep; + break; + case 0x20: /* GLBC */ + retval = opp->glbc; + break; + case 0x80: /* VENI */ + retval = opp->veni; + break; + case 0x90: /* PINT */ + retval = 0x00000000; + break; +#if MAX_IPI > 0 + case 0xA0: /* IPI_IPVP */ + case 0xB0: + case 0xC0: + case 0xD0: + { + int idx; + idx = (addr - 0xA0) >> 4; + retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP); + } + break; +#endif + case 0xE0: /* SPVE */ + retval = opp->spve; + break; + case 0xF0: /* TIFR */ + retval = opp->tifr; + break; + default: + break; + } + DPRINTF("%s: => %08x\n", __func__, retval); +#if defined OPENPIC_SWAP + retval = bswap32(retval); +#endif + + return retval; +} + +static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val) +{ + openpic_t *opp = opaque; + int idx; + + DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); + if (addr & 0xF) + return; +#if defined OPENPIC_SWAP + val = bswap32(val); +#endif + addr -= 0x1100; + addr &= 0xFFFF; + idx = (addr & 0xFFF0) >> 6; + addr = addr & 0x30; + switch (addr) { + case 0x00: /* TICC */ + break; + case 0x10: /* TIBC */ + if ((opp->timers[idx].ticc & 0x80000000) != 0 && + (val & 0x800000000) == 0 && + (opp->timers[idx].tibc & 0x80000000) != 0) + opp->timers[idx].ticc &= ~0x80000000; + opp->timers[idx].tibc = val; + break; + case 0x20: /* TIVP */ + write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP, val); + break; + case 0x30: /* TIDE */ + write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE, val); + break; + } +} + +static uint32_t openpic_timer_read (void *opaque, uint32_t addr) +{ + openpic_t *opp = opaque; + uint32_t retval; + int idx; + + DPRINTF("%s: addr %08x\n", __func__, addr); + retval = 0xFFFFFFFF; + if (addr & 0xF) + return retval; + addr -= 0x1100; + addr &= 0xFFFF; + idx = (addr & 0xFFF0) >> 6; + addr = addr & 0x30; + switch (addr) { + case 0x00: /* TICC */ + retval = opp->timers[idx].ticc; + break; + case 0x10: /* TIBC */ + retval = opp->timers[idx].tibc; + break; + case 0x20: /* TIPV */ + retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP); + break; + case 0x30: /* TIDE */ + retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE); + break; + } + DPRINTF("%s: => %08x\n", __func__, retval); +#if defined OPENPIC_SWAP + retval = bswap32(retval); +#endif + + return retval; +} + +static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val) +{ + openpic_t *opp = opaque; + int idx; + + DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); + if (addr & 0xF) + return; +#if defined OPENPIC_SWAP + val = tswap32(val); +#endif + addr = addr & 0xFFF0; + idx = addr >> 5; + if (addr & 0x10) { + /* EXDE / IFEDE / IEEDE */ + write_IRQreg(opp, idx, IRQ_IDE, val); + } else { + /* EXVP / IFEVP / IEEVP */ + write_IRQreg(opp, idx, IRQ_IPVP, val); + } +} + +static uint32_t openpic_src_read (void *opaque, uint32_t addr) +{ + openpic_t *opp = opaque; + uint32_t retval; + int idx; + + DPRINTF("%s: addr %08x\n", __func__, addr); + retval = 0xFFFFFFFF; + if (addr & 0xF) + return retval; + addr = addr & 0xFFF0; + idx = addr >> 5; + if (addr & 0x10) { + /* EXDE / IFEDE / IEEDE */ + retval = read_IRQreg(opp, idx, IRQ_IDE); + } else { + /* EXVP / IFEVP / IEEVP */ + retval = read_IRQreg(opp, idx, IRQ_IPVP); + } + DPRINTF("%s: => %08x\n", __func__, retval); +#if defined OPENPIC_SWAP + retval = tswap32(retval); +#endif + + return retval; +} + +static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val) +{ + openpic_t *opp = opaque; + IRQ_src_t *src; + IRQ_dst_t *dst; + int idx, n_IRQ; + + DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val); + if (addr & 0xF) + return; +#if defined OPENPIC_SWAP + val = bswap32(val); +#endif + addr &= 0x1FFF0; + idx = addr / 0x1000; + dst = &opp->dst[idx]; + addr &= 0xFF0; + switch (addr) { +#if MAX_IPI > 0 + case 0x40: /* PIPD */ + case 0x50: + case 0x60: + case 0x70: + idx = (addr - 0x40) >> 4; + write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE, val); + openpic_set_irq(opp, IRQ_IPI0 + idx, 1); + openpic_set_irq(opp, IRQ_IPI0 + idx, 0); + break; +#endif + case 0x80: /* PCTP */ + dst->pctp = val & 0x0000000F; + break; + case 0x90: /* WHOAMI */ + /* Read-only register */ + break; + case 0xA0: /* PIAC */ + /* Read-only register */ + break; + case 0xB0: /* PEOI */ + DPRINTF("PEOI\n"); + n_IRQ = IRQ_get_next(opp, &dst->servicing); + IRQ_resetbit(&dst->servicing, n_IRQ); + dst->servicing.next = -1; + src = &opp->src[n_IRQ]; + /* Set up next servicing IRQ */ + IRQ_get_next(opp, &dst->servicing); + /* Check queued interrupts. */ + n_IRQ = IRQ_get_next(opp, &dst->raised); + if (n_IRQ != -1) { + src = &opp->src[n_IRQ]; + if (IPVP_PRIORITY(src->ipvp) > dst->servicing.priority) { + DPRINTF("Raise CPU IRQ\n"); + cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD); + } + } + break; + default: + break; + } +} + +static uint32_t openpic_cpu_read (void *opaque, uint32_t addr) +{ + openpic_t *opp = opaque; + IRQ_src_t *src; + IRQ_dst_t *dst; + uint32_t retval; + int idx, n_IRQ; + + DPRINTF("%s: addr %08x\n", __func__, addr); + retval = 0xFFFFFFFF; + if (addr & 0xF) + return retval; + addr &= 0x1FFF0; + idx = addr / 0x1000; + dst = &opp->dst[idx]; + addr &= 0xFF0; + switch (addr) { + case 0x80: /* PCTP */ + retval = dst->pctp; + break; + case 0x90: /* WHOAMI */ + retval = idx; + break; + case 0xA0: /* PIAC */ + n_IRQ = IRQ_get_next(opp, &dst->raised); + DPRINTF("PIAC: irq=%d\n", n_IRQ); + if (n_IRQ == -1) { + /* No more interrupt pending */ + retval = opp->spve; + } else { + src = &opp->src[n_IRQ]; + if (!test_bit(&src->ipvp, IPVP_ACTIVITY) || + !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) { + /* - Spurious level-sensitive IRQ + * - Priorities has been changed + * and the pending IRQ isn't allowed anymore + */ + reset_bit(&src->ipvp, IPVP_ACTIVITY); + retval = IPVP_VECTOR(opp->spve); + } else { + /* IRQ enter servicing state */ + IRQ_setbit(&dst->servicing, n_IRQ); + retval = IPVP_VECTOR(src->ipvp); + } + IRQ_resetbit(&dst->raised, n_IRQ); + dst->raised.next = -1; + if (!test_bit(&src->ipvp, IPVP_SENSE)) { + /* edge-sensitive IRQ */ + reset_bit(&src->ipvp, IPVP_ACTIVITY); + src->pending = 0; + } + } + break; + case 0xB0: /* PEOI */ + retval = 0; + break; +#if MAX_IPI > 0 + case 0x40: /* IDE */ + case 0x50: + idx = (addr - 0x40) >> 4; + retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE); + break; +#endif + default: + break; + } + DPRINTF("%s: => %08x\n", __func__, retval); +#if defined OPENPIC_SWAP + retval= bswap32(retval); +#endif + + return retval; +} + +static void openpic_buggy_write (void *opaque, + target_phys_addr_t addr, uint32_t val) +{ + printf("Invalid OPENPIC write access !\n"); +} + +static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr) +{ + printf("Invalid OPENPIC read access !\n"); + + return -1; +} + +static void openpic_writel (void *opaque, + target_phys_addr_t addr, uint32_t val) +{ + openpic_t *opp = opaque; + + addr &= 0x3FFFF; + DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val); + if (addr < 0x1100) { + /* Global registers */ + openpic_gbl_write(opp, addr, val); + } else if (addr < 0x10000) { + /* Timers registers */ + openpic_timer_write(opp, addr, val); + } else if (addr < 0x20000) { + /* Source registers */ + openpic_src_write(opp, addr, val); + } else { + /* CPU registers */ + openpic_cpu_write(opp, addr, val); + } +} + +static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr) +{ + openpic_t *opp = opaque; + uint32_t retval; + + addr &= 0x3FFFF; + DPRINTF("%s: offset %08x\n", __func__, (int)addr); + if (addr < 0x1100) { + /* Global registers */ + retval = openpic_gbl_read(opp, addr); + } else if (addr < 0x10000) { + /* Timers registers */ + retval = openpic_timer_read(opp, addr); + } else if (addr < 0x20000) { + /* Source registers */ + retval = openpic_src_read(opp, addr); + } else { + /* CPU registers */ + retval = openpic_cpu_read(opp, addr); + } + + return retval; +} + +static CPUWriteMemoryFunc *openpic_write[] = { + &openpic_buggy_write, + &openpic_buggy_write, + &openpic_writel, +}; + +static CPUReadMemoryFunc *openpic_read[] = { + &openpic_buggy_read, + &openpic_buggy_read, + &openpic_readl, +}; + +static void openpic_map(PCIDevice *pci_dev, int region_num, + uint32_t addr, uint32_t size, int type) +{ + openpic_t *opp; + + DPRINTF("Map OpenPIC\n"); + opp = (openpic_t *)pci_dev; + /* Global registers */ + DPRINTF("Register OPENPIC gbl %08x => %08x\n", + addr + 0x1000, addr + 0x1000 + 0x100); + /* Timer registers */ + DPRINTF("Register OPENPIC timer %08x => %08x\n", + addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR); + /* Interrupt source registers */ + DPRINTF("Register OPENPIC src %08x => %08x\n", + addr + 0x10000, addr + 0x10000 + 0x20 * (EXT_IRQ + 2)); + /* Per CPU registers */ + DPRINTF("Register OPENPIC dst %08x => %08x\n", + addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU); + cpu_register_physical_memory(addr, 0x40000, opp->mem_index); +#if 0 // Don't implement ISU for now + opp_io_memory = cpu_register_io_memory(0, openpic_src_read, + openpic_src_write); + cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2), + opp_io_memory); +#endif +} + +openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus) +{ + openpic_t *opp; + uint8_t *pci_conf; + int i, m; + + /* XXX: for now, only one CPU is supported */ + if (nb_cpus != 1) + return NULL; + if (bus) { + opp = (openpic_t *)pci_register_device(bus, "OpenPIC", sizeof(openpic_t), + -1, NULL, NULL); + if (opp == NULL) + return NULL; + pci_conf = opp->pci_dev.config; + pci_conf[0x00] = 0x14; // IBM MPIC2 + pci_conf[0x01] = 0x10; + pci_conf[0x02] = 0xFF; + pci_conf[0x03] = 0xFF; + pci_conf[0x0a] = 0x80; // PIC + pci_conf[0x0b] = 0x08; + pci_conf[0x0e] = 0x00; // header_type + pci_conf[0x3d] = 0x00; // no interrupt pin + + /* Register I/O spaces */ + pci_register_io_region((PCIDevice *)opp, 0, 0x40000, + PCI_ADDRESS_SPACE_MEM, &openpic_map); + } else { + opp = qemu_mallocz(sizeof(openpic_t)); + } + + opp->mem_index = cpu_register_io_memory(0, openpic_read, + openpic_write, opp); + + // isu_base &= 0xFFFC0000; + opp->nb_cpus = nb_cpus; + /* Set IRQ types */ + for (i = 0; i < EXT_IRQ; i++) { + opp->src[i].type = IRQ_EXTERNAL; + } + for (; i < IRQ_TIM0; i++) { + opp->src[i].type = IRQ_SPECIAL; + } +#if MAX_IPI > 0 + m = IRQ_IPI0; +#else + m = IRQ_DBL0; +#endif + for (; i < m; i++) { + opp->src[i].type = IRQ_TIMER; + } + for (; i < MAX_IRQ; i++) { + opp->src[i].type = IRQ_INTERNAL; + } + openpic_reset(opp); + if (pmem_index) + *pmem_index = opp->mem_index; + return opp; +} diff --git a/tools/ioemu/hw/pc.c b/tools/ioemu/hw/pc.c new file mode 100644 index 0000000000..7bd85e7372 --- /dev/null +++ b/tools/ioemu/hw/pc.c @@ -0,0 +1,575 @@ +/* + * QEMU PC System Emulator + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +/* output Bochs bios info messages */ +//#define DEBUG_BIOS + +#define BIOS_FILENAME "bios.bin" +#define VGABIOS_FILENAME "vgabios.bin" +#define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin" +#define LINUX_BOOT_FILENAME "linux_boot.bin" + +#define KERNEL_LOAD_ADDR 0x00100000 +#define INITRD_LOAD_ADDR 0x00400000 +#define KERNEL_PARAMS_ADDR 0x00090000 +#define KERNEL_CMDLINE_ADDR 0x00099000 + +int speaker_data_on; +int dummy_refresh_clock; +static fdctrl_t *floppy_controller; +static RTCState *rtc_state; +static PITState *pit; + +static void ioport80_write(void *opaque, uint32_t addr, uint32_t data) +{ +} + +/* MSDOS compatibility mode FPU exception support */ +/* XXX: add IGNNE support */ +void cpu_set_ferr(CPUX86State *s) +{ + pic_set_irq(13, 1); +} + +static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data) +{ + pic_set_irq(13, 0); +} + +/* TSC handling */ + +uint64_t cpu_get_tsc(CPUX86State *env) +{ + return qemu_get_clock(vm_clock); +} + +/* PC cmos mappings */ + +#define REG_EQUIPMENT_BYTE 0x14 +#define REG_IBM_CENTURY_BYTE 0x32 +#define REG_IBM_PS2_CENTURY_BYTE 0x37 + + +static inline int to_bcd(RTCState *s, int a) +{ + return ((a / 10) << 4) | (a % 10); +} + +static int cmos_get_fd_drive_type(int fd0) +{ + int val; + + switch (fd0) { + case 0: + /* 1.44 Mb 3"5 drive */ + val = 4; + break; + case 1: + /* 2.88 Mb 3"5 drive */ + val = 5; + break; + case 2: + /* 1.2 Mb 5"5 drive */ + val = 2; + break; + default: + val = 0; + break; + } + return val; +} + +static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd) +{ + RTCState *s = rtc_state; + int cylinders, heads, sectors; + bdrv_get_geometry_hint(hd, &cylinders, &heads, §ors); + rtc_set_memory(s, type_ofs, 47); + rtc_set_memory(s, info_ofs, cylinders); + rtc_set_memory(s, info_ofs + 1, cylinders >> 8); + rtc_set_memory(s, info_ofs + 2, heads); + rtc_set_memory(s, info_ofs + 3, 0xff); + rtc_set_memory(s, info_ofs + 4, 0xff); + rtc_set_memory(s, info_ofs + 5, 0xc0 | ((heads > 8) << 3)); + rtc_set_memory(s, info_ofs + 6, cylinders); + rtc_set_memory(s, info_ofs + 7, cylinders >> 8); + rtc_set_memory(s, info_ofs + 8, sectors); +} + +/* hd_table must contain 4 block drivers */ +static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table) +{ + RTCState *s = rtc_state; + int val; + int fd0, fd1, nb; + time_t ti; + struct tm *tm; + int i; + + /* set the CMOS date */ + time(&ti); + if (rtc_utc) + tm = gmtime(&ti); + else + tm = localtime(&ti); + rtc_set_date(s, tm); + + val = to_bcd(s, (tm->tm_year / 100) + 19); + rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val); + rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val); + + /* various important CMOS locations needed by PC/Bochs bios */ + + /* memory size */ + val = 640; /* base memory in K */ + rtc_set_memory(s, 0x15, val); + rtc_set_memory(s, 0x16, val >> 8); + + val = (ram_size / 1024) - 1024; + if (val > 65535) + val = 65535; + rtc_set_memory(s, 0x17, val); + rtc_set_memory(s, 0x18, val >> 8); + rtc_set_memory(s, 0x30, val); + rtc_set_memory(s, 0x31, val >> 8); + + if (ram_size > (16 * 1024 * 1024)) + val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536); + else + val = 0; + if (val > 65535) + val = 65535; + rtc_set_memory(s, 0x34, val); + rtc_set_memory(s, 0x35, val >> 8); + + switch(boot_device) { + case 'a': + case 'b': + rtc_set_memory(s, 0x3d, 0x01); /* floppy boot */ + break; + default: + case 'c': + rtc_set_memory(s, 0x3d, 0x02); /* hard drive boot */ + break; + case 'd': + rtc_set_memory(s, 0x3d, 0x03); /* CD-ROM boot */ + break; + } + + /* floppy type */ + + fd0 = fdctrl_get_drive_type(floppy_controller, 0); + fd1 = fdctrl_get_drive_type(floppy_controller, 1); + + val = (cmos_get_fd_drive_type(fd0) << 4) | cmos_get_fd_drive_type(fd1); + rtc_set_memory(s, 0x10, val); + + val = 0; + nb = 0; + if (fd0 < 3) + nb++; + if (fd1 < 3) + nb++; + switch (nb) { + case 0: + break; + case 1: + val |= 0x01; /* 1 drive, ready for boot */ + break; + case 2: + val |= 0x41; /* 2 drives, ready for boot */ + break; + } + val |= 0x02; /* FPU is there */ + val |= 0x04; /* PS/2 mouse installed */ + rtc_set_memory(s, REG_EQUIPMENT_BYTE, val); + + /* hard drives */ + + rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0)); + if (hd_table[0]) + cmos_init_hd(0x19, 0x1b, hd_table[0]); + if (hd_table[1]) + cmos_init_hd(0x1a, 0x24, hd_table[1]); + + val = 0; + for (i = 0; i < 4; i++) { + if (hd_table[i]) { + int cylinders, heads, sectors; + uint8_t translation; + /* NOTE: bdrv_get_geometry_hint() returns the geometry + that the hard disk returns. It is always such that: 1 <= + sects <= 63, 1 <= heads <= 16, 1 <= cylinders <= + 16383. The BIOS geometry can be different. */ + bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, §ors); + if (cylinders <= 1024 && heads <= 16 && sectors <= 63) { + /* No translation. */ + translation = 0; + } else { + /* LBA translation. */ + translation = 1; + } + val |= translation << (i * 2); + } + } + rtc_set_memory(s, 0x39, val); + + /* Disable check of 0x55AA signature on the last two bytes of + first sector of disk. XXX: make it the default ? */ + // rtc_set_memory(s, 0x38, 1); +} + +static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ + speaker_data_on = (val >> 1) & 1; + pit_set_gate(pit, 2, val & 1); +} + +static uint32_t speaker_ioport_read(void *opaque, uint32_t addr) +{ + int out; + out = pit_get_out(pit, 2, qemu_get_clock(vm_clock)); + dummy_refresh_clock ^= 1; + return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) | + (dummy_refresh_clock << 4); +} + +static void ioport92_write(void *opaque, uint32_t addr, uint32_t val) +{ + cpu_x86_set_a20(cpu_single_env, (val >> 1) & 1); + /* XXX: bit 0 is fast reset */ +} + +static uint32_t ioport92_read(void *opaque, uint32_t addr) +{ + return ((cpu_single_env->a20_mask >> 20) & 1) << 1; +} + +/***********************************************************/ +/* Bochs BIOS debug ports */ + +void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val) +{ + static const char shutdown_str[8] = "Shutdown"; + static int shutdown_index = 0; + + switch(addr) { + /* Bochs BIOS messages */ + case 0x400: + case 0x401: + fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val); + exit(1); + case 0x402: + case 0x403: +#ifdef DEBUG_BIOS + fprintf(stderr, "%c", val); +#endif + break; + case 0x8900: + /* same as Bochs power off */ + if (val == shutdown_str[shutdown_index]) { + shutdown_index++; + if (shutdown_index == 8) { + shutdown_index = 0; + qemu_system_shutdown_request(); + } + } else { + shutdown_index = 0; + } + break; + + /* LGPL'ed VGA BIOS messages */ + case 0x501: + case 0x502: + fprintf(stderr, "VGA BIOS panic, line %d\n", val); + exit(1); + case 0x500: + case 0x503: +#ifdef DEBUG_BIOS + fprintf(stderr, "%c", val); +#endif + break; + } +} + +void bochs_bios_init(void) +{ + register_ioport_write(0x400, 1, 2, bochs_bios_write, NULL); + register_ioport_write(0x401, 1, 2, bochs_bios_write, NULL); + register_ioport_write(0x402, 1, 1, bochs_bios_write, NULL); + register_ioport_write(0x403, 1, 1, bochs_bios_write, NULL); + register_ioport_write(0x8900, 1, 1, bochs_bios_write, NULL); + + register_ioport_write(0x501, 1, 2, bochs_bios_write, NULL); + register_ioport_write(0x502, 1, 2, bochs_bios_write, NULL); + register_ioport_write(0x500, 1, 1, bochs_bios_write, NULL); + register_ioport_write(0x503, 1, 1, bochs_bios_write, NULL); +} + + +int load_kernel(const char *filename, uint8_t *addr, + uint8_t *real_addr) +{ + int fd, size; + int setup_sects; + + fd = open(filename, O_RDONLY | O_BINARY); + if (fd < 0) + return -1; + + /* load 16 bit code */ + if (read(fd, real_addr, 512) != 512) + goto fail; + setup_sects = real_addr[0x1F1]; + if (!setup_sects) + setup_sects = 4; + if (read(fd, real_addr + 512, setup_sects * 512) != + setup_sects * 512) + goto fail; + + /* load 32 bit code */ + size = read(fd, addr, 16 * 1024 * 1024); + if (size < 0) + goto fail; + close(fd); + return size; + fail: + close(fd); + return -1; +} + +static const int ide_iobase[2] = { 0x1f0, 0x170 }; +static const int ide_iobase2[2] = { 0x3f6, 0x376 }; +static const int ide_irq[2] = { 14, 15 }; + +#define NE2000_NB_MAX 6 + +static int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 }; +static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 }; + +static int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; +static int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 }; + +#define NOBIOS 1 + +/* PC hardware initialisation */ +void pc_init(int ram_size, int vga_ram_size, int boot_device, + DisplayState *ds, const char **fd_filename, int snapshot, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename) +{ + char buf[1024]; + int ret, linux_boot, initrd_size, i, nb_nics1; + unsigned long bios_offset, vga_bios_offset; + int bios_size, isa_bios_size; + PCIBus *pci_bus; + + linux_boot = (kernel_filename != NULL); + + /* allocate RAM */ +// cpu_register_physical_memory(0, ram_size, 0); + +#ifndef NOBIOS + /* BIOS load */ + bios_offset = ram_size + vga_ram_size; + vga_bios_offset = bios_offset + 256 * 1024; + + snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME); + bios_size = get_image_size(buf); + if (bios_size <= 0 || + (bios_size % 65536) != 0 || + bios_size > (256 * 1024)) { + goto bios_error; + } + ret = load_image(buf, phys_ram_base + bios_offset); + if (ret != bios_size) { + bios_error: + fprintf(stderr, "qemu: could not load PC bios '%s'\n", buf); + exit(1); + } + + /* VGA BIOS load */ + if (cirrus_vga_enabled) { + snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME); + } else { + snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME); + } + ret = load_image(buf, phys_ram_base + vga_bios_offset); +#endif + + /* setup basic memory access */ + cpu_register_physical_memory(0xc0000, 0x10000, + vga_bios_offset | IO_MEM_ROM); + +#ifndef NOBIOS + /* map the last 128KB of the BIOS in ISA space */ + isa_bios_size = bios_size; + if (isa_bios_size > (128 * 1024)) + isa_bios_size = 128 * 1024; + cpu_register_physical_memory(0xd0000, (192 * 1024) - isa_bios_size, + IO_MEM_UNASSIGNED); + cpu_register_physical_memory(0x100000 - isa_bios_size, + isa_bios_size, + (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM); + /* map all the bios at the top of memory */ + cpu_register_physical_memory((uint32_t)(-bios_size), + bios_size, bios_offset | IO_MEM_ROM); + + bochs_bios_init(); +#endif + + if (linux_boot) { + uint8_t bootsect[512]; + uint8_t old_bootsect[512]; + + if (bs_table[0] == NULL) { + fprintf(stderr, "A disk image must be given for 'hda' when booting a Linux kernel\n"); + exit(1); + } + snprintf(buf, sizeof(buf), "%s/%s", bios_dir, LINUX_BOOT_FILENAME); + ret = load_image(buf, bootsect); + if (ret != sizeof(bootsect)) { + fprintf(stderr, "qemu: could not load linux boot sector '%s'\n", + buf); + exit(1); + } + + if (bdrv_read(bs_table[0], 0, old_bootsect, 1) >= 0) { + /* copy the MSDOS partition table */ + memcpy(bootsect + 0x1be, old_bootsect + 0x1be, 0x40); + } + + bdrv_set_boot_sector(bs_table[0], bootsect, sizeof(bootsect)); + + /* now we can load the kernel */ + ret = load_kernel(kernel_filename, + phys_ram_base + KERNEL_LOAD_ADDR, + phys_ram_base + KERNEL_PARAMS_ADDR); + if (ret < 0) { + fprintf(stderr, "qemu: could not load kernel '%s'\n", + kernel_filename); + exit(1); + } + + /* load initrd */ + initrd_size = 0; + if (initrd_filename) { + initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR); + if (initrd_size < 0) { + fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", + initrd_filename); + exit(1); + } + } + if (initrd_size > 0) { + stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, INITRD_LOAD_ADDR); + stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x21c, initrd_size); + } + pstrcpy(phys_ram_base + KERNEL_CMDLINE_ADDR, 4096, + kernel_cmdline); + stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x20, 0xA33F); + stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x22, + KERNEL_CMDLINE_ADDR - KERNEL_PARAMS_ADDR); + /* loader type */ + stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x210, 0x01); + } + + if (pci_enabled) { + pci_bus = i440fx_init(); + piix3_init(pci_bus); + } else { + pci_bus = NULL; + } + + /* init basic PC hardware */ + register_ioport_write(0x80, 1, 1, ioport80_write, NULL); + + register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL); + +#ifdef NOBIOS + cirrus_vga_enabled = 0; +#endif + if (cirrus_vga_enabled) { + if (pci_enabled) { + pci_cirrus_vga_init(pci_bus, + ds, phys_ram_base + ram_size, ram_size, + vga_ram_size); + } else { + isa_cirrus_vga_init(ds, phys_ram_base + ram_size, ram_size, + vga_ram_size); + } + } else { + vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size, + vga_ram_size); + } + + rtc_state = rtc_init(0x70, 8); + register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL); + register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL); + + register_ioport_read(0x92, 1, 1, ioport92_read, NULL); + register_ioport_write(0x92, 1, 1, ioport92_write, NULL); + + pic_init(); + pit = pit_init(0x40, 0); + + for(i = 0; i < MAX_SERIAL_PORTS; i++) { + if (serial_hds[i]) { + serial_init(serial_io[i], serial_irq[i], serial_hds[i]); + } + } + + if (pci_enabled) { + for(i = 0; i < nb_nics; i++) { + pci_ne2000_init(pci_bus, &nd_table[i]); + } + pci_piix3_ide_init(pci_bus, bs_table); + } else { + nb_nics1 = nb_nics; + if (nb_nics1 > NE2000_NB_MAX) + nb_nics1 = NE2000_NB_MAX; + for(i = 0; i < nb_nics1; i++) { + isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]); + } + + for(i = 0; i < 2; i++) { + isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i], + bs_table[2 * i], bs_table[2 * i + 1]); + } + } + + kbd_init(); + DMA_init(0); + + floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table); + + cmos_init(ram_size, boot_device, bs_table); + + /* must be done after all PCI devices are instanciated */ + /* XXX: should be done in the Bochs BIOS */ + if (pci_enabled) { + pci_bios_init(); + } +} diff --git a/tools/ioemu/hw/pci.c b/tools/ioemu/hw/pci.c new file mode 100644 index 0000000000..2fed66f0a1 --- /dev/null +++ b/tools/ioemu/hw/pci.c @@ -0,0 +1,1524 @@ +/* + * QEMU PCI bus manager + * + * Copyright (c) 2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +//#define DEBUG_PCI + +#define PCI_VENDOR_ID 0x00 /* 16 bits */ +#define PCI_DEVICE_ID 0x02 /* 16 bits */ +#define PCI_COMMAND 0x04 /* 16 bits */ +#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ +#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ +#define PCI_CLASS_DEVICE 0x0a /* Device class */ +#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ +#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ +#define PCI_MIN_GNT 0x3e /* 8 bits */ +#define PCI_MAX_LAT 0x3f /* 8 bits */ + +/* just used for simpler irq handling. */ +#define PCI_DEVICES_MAX 64 +#define PCI_IRQ_WORDS ((PCI_DEVICES_MAX + 31) / 32) + +struct PCIBus { + int bus_num; + int devfn_min; + void (*set_irq)(PCIDevice *pci_dev, int irq_num, int level); + uint32_t config_reg; /* XXX: suppress */ + openpic_t *openpic; /* XXX: suppress */ + PCIDevice *devices[256]; +}; + +target_phys_addr_t pci_mem_base; +static int pci_irq_index; +static uint32_t pci_irq_levels[4][PCI_IRQ_WORDS]; +static PCIBus *first_bus; + +static PCIBus *pci_register_bus(void) +{ + PCIBus *bus; + bus = qemu_mallocz(sizeof(PCIBus)); + first_bus = bus; + return bus; +} + +void generic_pci_save(QEMUFile* f, void *opaque) +{ + PCIDevice* s=(PCIDevice*)opaque; + + qemu_put_buffer(f, s->config, 256); +} + +int generic_pci_load(QEMUFile* f, void *opaque, int version_id) +{ + PCIDevice* s=(PCIDevice*)opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_buffer(f, s->config, 256); + return 0; +} + +/* -1 for devfn means auto assign */ +PCIDevice *pci_register_device(PCIBus *bus, const char *name, + int instance_size, int devfn, + PCIConfigReadFunc *config_read, + PCIConfigWriteFunc *config_write) +{ + PCIDevice *pci_dev; + + if (pci_irq_index >= PCI_DEVICES_MAX) + return NULL; + + if (devfn < 0) { + for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) { + if (!bus->devices[devfn]) + goto found; + } + return NULL; + found: ; + } + pci_dev = qemu_mallocz(instance_size); + if (!pci_dev) + return NULL; + pci_dev->bus = bus; + pci_dev->devfn = devfn; + pstrcpy(pci_dev->name, sizeof(pci_dev->name), name); + + if (!config_read) + config_read = pci_default_read_config; + if (!config_write) + config_write = pci_default_write_config; + pci_dev->config_read = config_read; + pci_dev->config_write = config_write; + pci_dev->irq_index = pci_irq_index++; + bus->devices[devfn] = pci_dev; + return pci_dev; +} + +void pci_register_io_region(PCIDevice *pci_dev, int region_num, + uint32_t size, int type, + PCIMapIORegionFunc *map_func) +{ + PCIIORegion *r; + + if ((unsigned int)region_num >= PCI_NUM_REGIONS) + return; + r = &pci_dev->io_regions[region_num]; + r->addr = -1; + r->size = size; + r->type = type; + r->map_func = map_func; +} + +static void pci_addr_writel(void* opaque, uint32_t addr, uint32_t val) +{ + PCIBus *s = opaque; + s->config_reg = val; +} + +static uint32_t pci_addr_readl(void* opaque, uint32_t addr) +{ + PCIBus *s = opaque; + return s->config_reg; +} + +static void pci_update_mappings(PCIDevice *d) +{ + PCIIORegion *r; + int cmd, i; + uint32_t last_addr, new_addr, config_ofs; + + cmd = le16_to_cpu(*(uint16_t *)(d->config + PCI_COMMAND)); + for(i = 0; i < PCI_NUM_REGIONS; i++) { + r = &d->io_regions[i]; + if (i == PCI_ROM_SLOT) { + config_ofs = 0x30; + } else { + config_ofs = 0x10 + i * 4; + } + if (r->size != 0) { + if (r->type & PCI_ADDRESS_SPACE_IO) { + if (cmd & PCI_COMMAND_IO) { + new_addr = le32_to_cpu(*(uint32_t *)(d->config + + config_ofs)); + new_addr = new_addr & ~(r->size - 1); + last_addr = new_addr + r->size - 1; + /* NOTE: we have only 64K ioports on PC */ + if (last_addr <= new_addr || new_addr == 0 || + last_addr >= 0x10000) { + new_addr = -1; + } + } else { + new_addr = -1; + } + } else { + if (cmd & PCI_COMMAND_MEMORY) { + new_addr = le32_to_cpu(*(uint32_t *)(d->config + + config_ofs)); + /* the ROM slot has a specific enable bit */ + if (i == PCI_ROM_SLOT && !(new_addr & 1)) + goto no_mem_map; + new_addr = new_addr & ~(r->size - 1); + last_addr = new_addr + r->size - 1; + /* NOTE: we do not support wrapping */ + /* XXX: as we cannot support really dynamic + mappings, we handle specific values as invalid + mappings. */ + if (last_addr <= new_addr || new_addr == 0 || + last_addr == -1) { + new_addr = -1; + } + } else { + no_mem_map: + new_addr = -1; + } + } + /* now do the real mapping */ + if (new_addr != r->addr) { + if (r->addr != -1) { + if (r->type & PCI_ADDRESS_SPACE_IO) { + int class; + /* NOTE: specific hack for IDE in PC case: + only one byte must be mapped. */ + class = d->config[0x0a] | (d->config[0x0b] << 8); + if (class == 0x0101 && r->size == 4) { + isa_unassign_ioport(r->addr + 2, 1); + } else { + isa_unassign_ioport(r->addr, r->size); + } + } else { + cpu_register_physical_memory(r->addr + pci_mem_base, + r->size, + IO_MEM_UNASSIGNED); + } + } + r->addr = new_addr; + if (r->addr != -1) { + r->map_func(d, i, r->addr, r->size, r->type); + } + } + } + } +} + +uint32_t pci_default_read_config(PCIDevice *d, + uint32_t address, int len) +{ + uint32_t val; + switch(len) { + case 1: + val = d->config[address]; + break; + case 2: + val = le16_to_cpu(*(uint16_t *)(d->config + address)); + break; + default: + case 4: + val = le32_to_cpu(*(uint32_t *)(d->config + address)); + break; + } + return val; +} + +void pci_default_write_config(PCIDevice *d, + uint32_t address, uint32_t val, int len) +{ + int can_write, i; + uint32_t end, addr; + + if (len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) || + (address >= 0x30 && address < 0x34))) { + PCIIORegion *r; + int reg; + + if ( address >= 0x30 ) { + reg = PCI_ROM_SLOT; + }else{ + reg = (address - 0x10) >> 2; + } + r = &d->io_regions[reg]; + if (r->size == 0) + goto default_config; + /* compute the stored value */ + if (reg == PCI_ROM_SLOT) { + /* keep ROM enable bit */ + val &= (~(r->size - 1)) | 1; + } else { + val &= ~(r->size - 1); + val |= r->type; + } + *(uint32_t *)(d->config + address) = cpu_to_le32(val); + pci_update_mappings(d); + return; + } + default_config: + /* not efficient, but simple */ + addr = address; + for(i = 0; i < len; i++) { + /* default read/write accesses */ + switch(d->config[0x0e]) { + case 0x00: + case 0x80: + switch(addr) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0e: + case 0x10 ... 0x27: /* base */ + case 0x30 ... 0x33: /* rom */ + case 0x3d: + can_write = 0; + break; + default: + can_write = 1; + break; + } + break; + default: + case 0x01: + switch(addr) { + case 0x00: + case 0x01: + case 0x02: + case 0x03: + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0e: + case 0x38 ... 0x3b: /* rom */ + case 0x3d: + can_write = 0; + break; + default: + can_write = 1; + break; + } + break; + } + if (can_write) { + d->config[addr] = val; + } + addr++; + val >>= 8; + } + + end = address + len; + if (end > PCI_COMMAND && address < (PCI_COMMAND + 2)) { + /* if the command register is modified, we must modify the mappings */ + pci_update_mappings(d); + } +} + +static void pci_data_write(void *opaque, uint32_t addr, + uint32_t val, int len) +{ + PCIBus *s = opaque; + PCIDevice *pci_dev; + int config_addr, bus_num; + +#if defined(DEBUG_PCI) && 0 + printf("pci_data_write: addr=%08x val=%08x len=%d\n", + s->config_reg, val, len); +#endif + if (!(s->config_reg & (1 << 31))) { + return; + } + if ((s->config_reg & 0x3) != 0) { + return; + } + bus_num = (s->config_reg >> 16) & 0xff; + if (bus_num != 0) + return; + pci_dev = s->devices[(s->config_reg >> 8) & 0xff]; + if (!pci_dev) + return; + config_addr = (s->config_reg & 0xfc) | (addr & 3); +#if defined(DEBUG_PCI) + printf("pci_config_write: %s: addr=%02x val=%08x len=%d\n", + pci_dev->name, config_addr, val, len); +#endif + pci_dev->config_write(pci_dev, config_addr, val, len); +} + +static uint32_t pci_data_read(void *opaque, uint32_t addr, + int len) +{ + PCIBus *s = opaque; + PCIDevice *pci_dev; + int config_addr, bus_num; + uint32_t val; + + if (!(s->config_reg & (1 << 31))) + goto fail; + if ((s->config_reg & 0x3) != 0) + goto fail; + bus_num = (s->config_reg >> 16) & 0xff; + if (bus_num != 0) + goto fail; + pci_dev = s->devices[(s->config_reg >> 8) & 0xff]; + if (!pci_dev) { + fail: + switch(len) { + case 1: + val = 0xff; + break; + case 2: + val = 0xffff; + break; + default: + case 4: + val = 0xffffffff; + break; + } + goto the_end; + } + config_addr = (s->config_reg & 0xfc) | (addr & 3); + val = pci_dev->config_read(pci_dev, config_addr, len); +#if defined(DEBUG_PCI) + printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n", + pci_dev->name, config_addr, val, len); +#endif + the_end: +#if defined(DEBUG_PCI) && 0 + printf("pci_data_read: addr=%08x val=%08x len=%d\n", + s->config_reg, val, len); +#endif + return val; +} + +static void pci_data_writeb(void* opaque, uint32_t addr, uint32_t val) +{ + pci_data_write(opaque, addr, val, 1); +} + +static void pci_data_writew(void* opaque, uint32_t addr, uint32_t val) +{ + pci_data_write(opaque, addr, val, 2); +} + +static void pci_data_writel(void* opaque, uint32_t addr, uint32_t val) +{ + pci_data_write(opaque, addr, val, 4); +} + +static uint32_t pci_data_readb(void* opaque, uint32_t addr) +{ + return pci_data_read(opaque, addr, 1); +} + +static uint32_t pci_data_readw(void* opaque, uint32_t addr) +{ + return pci_data_read(opaque, addr, 2); +} + +static uint32_t pci_data_readl(void* opaque, uint32_t addr) +{ + return pci_data_read(opaque, addr, 4); +} + +/* i440FX PCI bridge */ + +static void piix3_set_irq(PCIDevice *pci_dev, int irq_num, int level); + +PCIBus *i440fx_init(void) +{ + PCIBus *s; + PCIDevice *d; + + s = pci_register_bus(); + s->set_irq = piix3_set_irq; + + register_ioport_write(0xcf8, 4, 4, pci_addr_writel, s); + register_ioport_read(0xcf8, 4, 4, pci_addr_readl, s); + + register_ioport_write(0xcfc, 4, 1, pci_data_writeb, s); + register_ioport_write(0xcfc, 4, 2, pci_data_writew, s); + register_ioport_write(0xcfc, 4, 4, pci_data_writel, s); + register_ioport_read(0xcfc, 4, 1, pci_data_readb, s); + register_ioport_read(0xcfc, 4, 2, pci_data_readw, s); + register_ioport_read(0xcfc, 4, 4, pci_data_readl, s); + + d = pci_register_device(s, "i440FX", sizeof(PCIDevice), 0, + NULL, NULL); + + d->config[0x00] = 0x86; // vendor_id + d->config[0x01] = 0x80; + d->config[0x02] = 0x37; // device_id + d->config[0x03] = 0x12; + d->config[0x08] = 0x02; // revision + d->config[0x0a] = 0x00; // class_sub = host2pci + d->config[0x0b] = 0x06; // class_base = PCI_bridge + d->config[0x0e] = 0x00; // header_type + return s; +} + +/* PIIX3 PCI to ISA bridge */ + +typedef struct PIIX3State { + PCIDevice dev; +} PIIX3State; + +PIIX3State *piix3_state; + +/* return the global irq number corresponding to a given device irq + pin. We could also use the bus number to have a more precise + mapping. */ +static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) +{ + int slot_addend; + slot_addend = (pci_dev->devfn >> 3); + return (irq_num + slot_addend) & 3; +} + +static void piix3_set_irq(PCIDevice *pci_dev, int irq_num, int level) +{ + int irq_index, shift, pic_irq, pic_level; + uint32_t *p; + + irq_num = pci_slot_get_pirq(pci_dev, irq_num); + irq_index = pci_dev->irq_index; + p = &pci_irq_levels[irq_num][irq_index >> 5]; + shift = (irq_index & 0x1f); + *p = (*p & ~(1 << shift)) | (level << shift); + + /* now we change the pic irq level according to the piix irq mappings */ + pic_irq = piix3_state->dev.config[0x60 + irq_num]; + if (pic_irq < 16) { + /* the pic level is the logical OR of all the PCI irqs mapped + to it */ + pic_level = 0; +#if (PCI_IRQ_WORDS == 2) + pic_level = ((pci_irq_levels[irq_num][0] | + pci_irq_levels[irq_num][1]) != 0); +#else + { + int i; + pic_level = 0; + for(i = 0; i < PCI_IRQ_WORDS; i++) { + if (pci_irq_levels[irq_num][i]) { + pic_level = 1; + break; + } + } + } +#endif + pic_set_irq(pic_irq, pic_level); + } +} + +static void piix3_reset(PIIX3State *d) +{ + uint8_t *pci_conf = d->dev.config; + + pci_conf[0x04] = 0x07; // master, memory and I/O + pci_conf[0x05] = 0x00; + pci_conf[0x06] = 0x00; + pci_conf[0x07] = 0x02; // PCI_status_devsel_medium + pci_conf[0x4c] = 0x4d; + pci_conf[0x4e] = 0x03; + pci_conf[0x4f] = 0x00; + pci_conf[0x60] = 0x80; + pci_conf[0x69] = 0x02; + pci_conf[0x70] = 0x80; + pci_conf[0x76] = 0x0c; + pci_conf[0x77] = 0x0c; + pci_conf[0x78] = 0x02; + pci_conf[0x79] = 0x00; + pci_conf[0x80] = 0x00; + pci_conf[0x82] = 0x00; + pci_conf[0xa0] = 0x08; + pci_conf[0xa0] = 0x08; + pci_conf[0xa2] = 0x00; + pci_conf[0xa3] = 0x00; + pci_conf[0xa4] = 0x00; + pci_conf[0xa5] = 0x00; + pci_conf[0xa6] = 0x00; + pci_conf[0xa7] = 0x00; + pci_conf[0xa8] = 0x0f; + pci_conf[0xaa] = 0x00; + pci_conf[0xab] = 0x00; + pci_conf[0xac] = 0x00; + pci_conf[0xae] = 0x00; +} + +void piix3_init(PCIBus *bus) +{ + PIIX3State *d; + uint8_t *pci_conf; + + d = (PIIX3State *)pci_register_device(bus, "PIIX3", sizeof(PIIX3State), + -1, NULL, NULL); + register_savevm("PIIX3", 0, 1, generic_pci_save, generic_pci_load, d); + + piix3_state = d; + pci_conf = d->dev.config; + + pci_conf[0x00] = 0x86; // Intel + pci_conf[0x01] = 0x80; + pci_conf[0x02] = 0x00; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1) + pci_conf[0x03] = 0x70; + pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA + pci_conf[0x0b] = 0x06; // class_base = PCI_bridge + pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic + + piix3_reset(d); +} + +/* PREP pci init */ + +static inline void set_config(PCIBus *s, target_phys_addr_t addr) +{ + int devfn, i; + + for(i = 0; i < 11; i++) { + if ((addr & (1 << (11 + i))) != 0) + break; + } + devfn = ((addr >> 8) & 7) | (i << 3); + s->config_reg = 0x80000000 | (addr & 0xfc) | (devfn << 8); +} + +static void PPC_PCIIO_writeb (void *opaque, target_phys_addr_t addr, uint32_t val) +{ + PCIBus *s = opaque; + set_config(s, addr); + pci_data_write(s, addr, val, 1); +} + +static void PPC_PCIIO_writew (void *opaque, target_phys_addr_t addr, uint32_t val) +{ + PCIBus *s = opaque; + set_config(s, addr); +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap16(val); +#endif + pci_data_write(s, addr, val, 2); +} + +static void PPC_PCIIO_writel (void *opaque, target_phys_addr_t addr, uint32_t val) +{ + PCIBus *s = opaque; + set_config(s, addr); +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + pci_data_write(s, addr, val, 4); +} + +static uint32_t PPC_PCIIO_readb (void *opaque, target_phys_addr_t addr) +{ + PCIBus *s = opaque; + uint32_t val; + set_config(s, addr); + val = pci_data_read(s, addr, 1); + return val; +} + +static uint32_t PPC_PCIIO_readw (void *opaque, target_phys_addr_t addr) +{ + PCIBus *s = opaque; + uint32_t val; + set_config(s, addr); + val = pci_data_read(s, addr, 2); +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap16(val); +#endif + return val; +} + +static uint32_t PPC_PCIIO_readl (void *opaque, target_phys_addr_t addr) +{ + PCIBus *s = opaque; + uint32_t val; + set_config(s, addr); + val = pci_data_read(s, addr, 4); +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + return val; +} + +static CPUWriteMemoryFunc *PPC_PCIIO_write[] = { + &PPC_PCIIO_writeb, + &PPC_PCIIO_writew, + &PPC_PCIIO_writel, +}; + +static CPUReadMemoryFunc *PPC_PCIIO_read[] = { + &PPC_PCIIO_readb, + &PPC_PCIIO_readw, + &PPC_PCIIO_readl, +}; + +static void prep_set_irq(PCIDevice *d, int irq_num, int level) +{ + /* XXX: we do not simulate the hardware - we rely on the BIOS to + set correctly for irq line field */ + pic_set_irq(d->config[PCI_INTERRUPT_LINE], level); +} + +PCIBus *pci_prep_init(void) +{ + PCIBus *s; + PCIDevice *d; + int PPC_io_memory; + + s = pci_register_bus(); + s->set_irq = prep_set_irq; + + PPC_io_memory = cpu_register_io_memory(0, PPC_PCIIO_read, + PPC_PCIIO_write, s); + cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory); + + d = pci_register_device(s, "PREP PCI Bridge", sizeof(PCIDevice), 0, + NULL, NULL); + + /* XXX: put correct IDs */ + d->config[0x00] = 0x11; // vendor_id + d->config[0x01] = 0x10; + d->config[0x02] = 0x26; // device_id + d->config[0x03] = 0x00; + d->config[0x08] = 0x02; // revision + d->config[0x0a] = 0x04; // class_sub = pci2pci + d->config[0x0b] = 0x06; // class_base = PCI_bridge + d->config[0x0e] = 0x01; // header_type + return s; +} + + +/* pmac pci init */ + +#if 0 +/* Grackle PCI host */ +static void pci_grackle_config_writel (void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + PCIBus *s = opaque; +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + s->config_reg = val; +} + +static uint32_t pci_grackle_config_readl (void *opaque, target_phys_addr_t addr) +{ + PCIBus *s = opaque; + uint32_t val; + + val = s->config_reg; +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + return val; +} + +static CPUWriteMemoryFunc *pci_grackle_config_write[] = { + &pci_grackle_config_writel, + &pci_grackle_config_writel, + &pci_grackle_config_writel, +}; + +static CPUReadMemoryFunc *pci_grackle_config_read[] = { + &pci_grackle_config_readl, + &pci_grackle_config_readl, + &pci_grackle_config_readl, +}; + +static void pci_grackle_writeb (void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + PCIBus *s = opaque; + pci_data_write(s, addr, val, 1); +} + +static void pci_grackle_writew (void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + PCIBus *s = opaque; +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap16(val); +#endif + pci_data_write(s, addr, val, 2); +} + +static void pci_grackle_writel (void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + PCIBus *s = opaque; +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + pci_data_write(s, addr, val, 4); +} + +static uint32_t pci_grackle_readb (void *opaque, target_phys_addr_t addr) +{ + PCIBus *s = opaque; + uint32_t val; + val = pci_data_read(s, addr, 1); + return val; +} + +static uint32_t pci_grackle_readw (void *opaque, target_phys_addr_t addr) +{ + PCIBus *s = opaque; + uint32_t val; + val = pci_data_read(s, addr, 2); +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap16(val); +#endif + return val; +} + +static uint32_t pci_grackle_readl (void *opaque, target_phys_addr_t addr) +{ + PCIBus *s = opaque; + uint32_t val; + + val = pci_data_read(s, addr, 4); +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + return val; +} + +static CPUWriteMemoryFunc *pci_grackle_write[] = { + &pci_grackle_writeb, + &pci_grackle_writew, + &pci_grackle_writel, +}; + +static CPUReadMemoryFunc *pci_grackle_read[] = { + &pci_grackle_readb, + &pci_grackle_readw, + &pci_grackle_readl, +}; +#endif + +/* Uninorth PCI host (for all Mac99 and newer machines */ +static void pci_unin_main_config_writel (void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + PCIBus *s = opaque; + int i; + +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + + for (i = 11; i < 32; i++) { + if ((val & (1 << i)) != 0) + break; + } +#if 0 + s->config_reg = 0x80000000 | (1 << 16) | (val & 0x7FC) | (i << 11); +#else + s->config_reg = 0x80000000 | (0 << 16) | (val & 0x7FC) | (i << 11); +#endif +} + +static uint32_t pci_unin_main_config_readl (void *opaque, + target_phys_addr_t addr) +{ + PCIBus *s = opaque; + uint32_t val; + int devfn; + + devfn = (s->config_reg >> 8) & 0xFF; + val = (1 << (devfn >> 3)) | ((devfn & 0x07) << 8) | (s->config_reg & 0xFC); +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + + return val; +} + +static CPUWriteMemoryFunc *pci_unin_main_config_write[] = { + &pci_unin_main_config_writel, + &pci_unin_main_config_writel, + &pci_unin_main_config_writel, +}; + +static CPUReadMemoryFunc *pci_unin_main_config_read[] = { + &pci_unin_main_config_readl, + &pci_unin_main_config_readl, + &pci_unin_main_config_readl, +}; + +static void pci_unin_main_writeb (void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + PCIBus *s = opaque; + pci_data_write(s, addr & 7, val, 1); +} + +static void pci_unin_main_writew (void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + PCIBus *s = opaque; +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap16(val); +#endif + pci_data_write(s, addr & 7, val, 2); +} + +static void pci_unin_main_writel (void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + PCIBus *s = opaque; +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + pci_data_write(s, addr & 7, val, 4); +} + +static uint32_t pci_unin_main_readb (void *opaque, target_phys_addr_t addr) +{ + PCIBus *s = opaque; + uint32_t val; + + val = pci_data_read(s, addr & 7, 1); + + return val; +} + +static uint32_t pci_unin_main_readw (void *opaque, target_phys_addr_t addr) +{ + PCIBus *s = opaque; + uint32_t val; + + val = pci_data_read(s, addr & 7, 2); +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap16(val); +#endif + + return val; +} + +static uint32_t pci_unin_main_readl (void *opaque, target_phys_addr_t addr) +{ + PCIBus *s = opaque; + uint32_t val; + + val = pci_data_read(s, addr, 4); +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + + return val; +} + +static CPUWriteMemoryFunc *pci_unin_main_write[] = { + &pci_unin_main_writeb, + &pci_unin_main_writew, + &pci_unin_main_writel, +}; + +static CPUReadMemoryFunc *pci_unin_main_read[] = { + &pci_unin_main_readb, + &pci_unin_main_readw, + &pci_unin_main_readl, +}; + +#if 0 + +static void pci_unin_config_writel (void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + PCIBus *s = opaque; + +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + s->config_reg = 0x80000000 | (val & ~0x00000001); +} + +static uint32_t pci_unin_config_readl (void *opaque, + target_phys_addr_t addr) +{ + PCIBus *s = opaque; + uint32_t val; + + val = (s->config_reg | 0x00000001) & ~0x80000000; +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + + return val; +} + +static CPUWriteMemoryFunc *pci_unin_config_write[] = { + &pci_unin_config_writel, + &pci_unin_config_writel, + &pci_unin_config_writel, +}; + +static CPUReadMemoryFunc *pci_unin_config_read[] = { + &pci_unin_config_readl, + &pci_unin_config_readl, + &pci_unin_config_readl, +}; + +static void pci_unin_writeb (void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + PCIBus *s = opaque; + pci_data_write(s, addr & 3, val, 1); +} + +static void pci_unin_writew (void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + PCIBus *s = opaque; +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap16(val); +#endif + pci_data_write(s, addr & 3, val, 2); +} + +static void pci_unin_writel (void *opaque, target_phys_addr_t addr, + uint32_t val) +{ + PCIBus *s = opaque; +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + pci_data_write(s, addr & 3, val, 4); +} + +static uint32_t pci_unin_readb (void *opaque, target_phys_addr_t addr) +{ + PCIBus *s = opaque; + uint32_t val; + + val = pci_data_read(s, addr & 3, 1); + + return val; +} + +static uint32_t pci_unin_readw (void *opaque, target_phys_addr_t addr) +{ + PCIBus *s = opaque; + uint32_t val; + + val = pci_data_read(s, addr & 3, 2); +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap16(val); +#endif + + return val; +} + +static uint32_t pci_unin_readl (void *opaque, target_phys_addr_t addr) +{ + PCIBus *s = opaque; + uint32_t val; + + val = pci_data_read(s, addr & 3, 4); +#ifdef TARGET_WORDS_BIGENDIAN + val = bswap32(val); +#endif + + return val; +} + +static CPUWriteMemoryFunc *pci_unin_write[] = { + &pci_unin_writeb, + &pci_unin_writew, + &pci_unin_writel, +}; + +static CPUReadMemoryFunc *pci_unin_read[] = { + &pci_unin_readb, + &pci_unin_readw, + &pci_unin_readl, +}; +#endif + +static void pmac_set_irq(PCIDevice *d, int irq_num, int level) +{ + openpic_t *openpic; + /* XXX: we do not simulate the hardware - we rely on the BIOS to + set correctly for irq line field */ + openpic = d->bus->openpic; +#ifdef TARGET_PPC + if (openpic) + openpic_set_irq(openpic, d->config[PCI_INTERRUPT_LINE], level); +#endif +} + +void pci_pmac_set_openpic(PCIBus *bus, openpic_t *openpic) +{ + bus->openpic = openpic; +} + +PCIBus *pci_pmac_init(void) +{ + PCIBus *s; + PCIDevice *d; + int pci_mem_config, pci_mem_data; + + /* Use values found on a real PowerMac */ + /* Uninorth main bus */ + s = pci_register_bus(); + s->set_irq = pmac_set_irq; + + pci_mem_config = cpu_register_io_memory(0, pci_unin_main_config_read, + pci_unin_main_config_write, s); + pci_mem_data = cpu_register_io_memory(0, pci_unin_main_read, + pci_unin_main_write, s); + cpu_register_physical_memory(0xf2800000, 0x1000, pci_mem_config); + cpu_register_physical_memory(0xf2c00000, 0x1000, pci_mem_data); + s->devfn_min = 11 << 3; + d = pci_register_device(s, "Uni-north main", sizeof(PCIDevice), + 11 << 3, NULL, NULL); + d->config[0x00] = 0x6b; // vendor_id : Apple + d->config[0x01] = 0x10; + d->config[0x02] = 0x1F; // device_id + d->config[0x03] = 0x00; + d->config[0x08] = 0x00; // revision + d->config[0x0A] = 0x00; // class_sub = pci host + d->config[0x0B] = 0x06; // class_base = PCI_bridge + d->config[0x0C] = 0x08; // cache_line_size + d->config[0x0D] = 0x10; // latency_timer + d->config[0x0E] = 0x00; // header_type + d->config[0x34] = 0x00; // capabilities_pointer + +#if 0 // XXX: not activated as PPC BIOS doesn't handle mutiple buses properly + /* pci-to-pci bridge */ + d = pci_register_device("Uni-north bridge", sizeof(PCIDevice), 0, 13 << 3, + NULL, NULL); + d->config[0x00] = 0x11; // vendor_id : TI + d->config[0x01] = 0x10; + d->config[0x02] = 0x26; // device_id + d->config[0x03] = 0x00; + d->config[0x08] = 0x05; // revision + d->config[0x0A] = 0x04; // class_sub = pci2pci + d->config[0x0B] = 0x06; // class_base = PCI_bridge + d->config[0x0C] = 0x08; // cache_line_size + d->config[0x0D] = 0x20; // latency_timer + d->config[0x0E] = 0x01; // header_type + + d->config[0x18] = 0x01; // primary_bus + d->config[0x19] = 0x02; // secondary_bus + d->config[0x1A] = 0x02; // subordinate_bus + d->config[0x1B] = 0x20; // secondary_latency_timer + d->config[0x1C] = 0x11; // io_base + d->config[0x1D] = 0x01; // io_limit + d->config[0x20] = 0x00; // memory_base + d->config[0x21] = 0x80; + d->config[0x22] = 0x00; // memory_limit + d->config[0x23] = 0x80; + d->config[0x24] = 0x01; // prefetchable_memory_base + d->config[0x25] = 0x80; + d->config[0x26] = 0xF1; // prefectchable_memory_limit + d->config[0x27] = 0x7F; + // d->config[0x34] = 0xdc // capabilities_pointer +#endif +#if 0 // XXX: not needed for now + /* Uninorth AGP bus */ + s = &pci_bridge[1]; + pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read, + pci_unin_config_write, s); + pci_mem_data = cpu_register_io_memory(0, pci_unin_read, + pci_unin_write, s); + cpu_register_physical_memory(0xf0800000, 0x1000, pci_mem_config); + cpu_register_physical_memory(0xf0c00000, 0x1000, pci_mem_data); + + d = pci_register_device("Uni-north AGP", sizeof(PCIDevice), 0, 11 << 3, + NULL, NULL); + d->config[0x00] = 0x6b; // vendor_id : Apple + d->config[0x01] = 0x10; + d->config[0x02] = 0x20; // device_id + d->config[0x03] = 0x00; + d->config[0x08] = 0x00; // revision + d->config[0x0A] = 0x00; // class_sub = pci host + d->config[0x0B] = 0x06; // class_base = PCI_bridge + d->config[0x0C] = 0x08; // cache_line_size + d->config[0x0D] = 0x10; // latency_timer + d->config[0x0E] = 0x00; // header_type + // d->config[0x34] = 0x80; // capabilities_pointer +#endif + +#if 0 // XXX: not needed for now + /* Uninorth internal bus */ + s = &pci_bridge[2]; + pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read, + pci_unin_config_write, s); + pci_mem_data = cpu_register_io_memory(0, pci_unin_read, + pci_unin_write, s); + cpu_register_physical_memory(0xf4800000, 0x1000, pci_mem_config); + cpu_register_physical_memory(0xf4c00000, 0x1000, pci_mem_data); + + d = pci_register_device("Uni-north internal", sizeof(PCIDevice), + 3, 11 << 3, NULL, NULL); + d->config[0x00] = 0x6b; // vendor_id : Apple + d->config[0x01] = 0x10; + d->config[0x02] = 0x1E; // device_id + d->config[0x03] = 0x00; + d->config[0x08] = 0x00; // revision + d->config[0x0A] = 0x00; // class_sub = pci host + d->config[0x0B] = 0x06; // class_base = PCI_bridge + d->config[0x0C] = 0x08; // cache_line_size + d->config[0x0D] = 0x10; // latency_timer + d->config[0x0E] = 0x00; // header_type + d->config[0x34] = 0x00; // capabilities_pointer +#endif + +#if 0 // Grackle ? + /* same values as PearPC - check this */ + d->config[0x00] = 0x11; // vendor_id + d->config[0x01] = 0x10; + d->config[0x02] = 0x26; // device_id + d->config[0x03] = 0x00; + d->config[0x08] = 0x02; // revision + d->config[0x0a] = 0x04; // class_sub = pci2pci + d->config[0x0b] = 0x06; // class_base = PCI_bridge + d->config[0x0e] = 0x01; // header_type + + d->config[0x18] = 0x0; // primary_bus + d->config[0x19] = 0x1; // secondary_bus + d->config[0x1a] = 0x1; // subordinate_bus + d->config[0x1c] = 0x10; // io_base + d->config[0x1d] = 0x20; // io_limit + + d->config[0x20] = 0x80; // memory_base + d->config[0x21] = 0x80; + d->config[0x22] = 0x90; // memory_limit + d->config[0x23] = 0x80; + + d->config[0x24] = 0x00; // prefetchable_memory_base + d->config[0x25] = 0x84; + d->config[0x26] = 0x00; // prefetchable_memory_limit + d->config[0x27] = 0x85; +#endif + return s; +} + +/***********************************************************/ +/* generic PCI irq support */ + +/* 0 <= irq_num <= 3. level must be 0 or 1 */ +void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level) +{ + PCIBus *bus = pci_dev->bus; + bus->set_irq(pci_dev, irq_num, level); +} + +/***********************************************************/ +/* monitor info on PCI */ + +static void pci_info_device(PCIDevice *d) +{ + int i, class; + PCIIORegion *r; + + term_printf(" Bus %2d, device %3d, function %d:\n", + d->bus->bus_num, d->devfn >> 3, d->devfn & 7); + class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE))); + term_printf(" "); + switch(class) { + case 0x0101: + term_printf("IDE controller"); + break; + case 0x0200: + term_printf("Ethernet controller"); + break; + case 0x0300: + term_printf("VGA controller"); + break; + default: + term_printf("Class %04x", class); + break; + } + term_printf(": PCI device %04x:%04x\n", + le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))), + le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID)))); + + if (d->config[PCI_INTERRUPT_PIN] != 0) { + term_printf(" IRQ %d.\n", d->config[PCI_INTERRUPT_LINE]); + } + for(i = 0;i < PCI_NUM_REGIONS; i++) { + r = &d->io_regions[i]; + if (r->size != 0) { + term_printf(" BAR%d: ", i); + if (r->type & PCI_ADDRESS_SPACE_IO) { + term_printf("I/O at 0x%04x [0x%04x].\n", + r->addr, r->addr + r->size - 1); + } else { + term_printf("32 bit memory at 0x%08x [0x%08x].\n", + r->addr, r->addr + r->size - 1); + } + } + } +} + +void pci_info(void) +{ + PCIBus *bus = first_bus; + PCIDevice *d; + int devfn; + + if (bus) { + for(devfn = 0; devfn < 256; devfn++) { + d = bus->devices[devfn]; + if (d) + pci_info_device(d); + } + } +} + +/***********************************************************/ +/* XXX: the following should be moved to the PC BIOS */ + +static __attribute__((unused)) uint32_t isa_inb(uint32_t addr) +{ + return cpu_inb(cpu_single_env, addr); +} + +static void isa_outb(uint32_t val, uint32_t addr) +{ + cpu_outb(cpu_single_env, addr, val); +} + +static __attribute__((unused)) uint32_t isa_inw(uint32_t addr) +{ + return cpu_inw(cpu_single_env, addr); +} + +static __attribute__((unused)) void isa_outw(uint32_t val, uint32_t addr) +{ + cpu_outw(cpu_single_env, addr, val); +} + +static __attribute__((unused)) uint32_t isa_inl(uint32_t addr) +{ + return cpu_inl(cpu_single_env, addr); +} + +static __attribute__((unused)) void isa_outl(uint32_t val, uint32_t addr) +{ + cpu_outl(cpu_single_env, addr, val); +} + +static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val) +{ + PCIBus *s = d->bus; + s->config_reg = 0x80000000 | (s->bus_num << 16) | + (d->devfn << 8) | addr; + pci_data_write(s, 0, val, 4); +} + +static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val) +{ + PCIBus *s = d->bus; + s->config_reg = 0x80000000 | (s->bus_num << 16) | + (d->devfn << 8) | (addr & ~3); + pci_data_write(s, addr & 3, val, 2); +} + +static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val) +{ + PCIBus *s = d->bus; + s->config_reg = 0x80000000 | (s->bus_num << 16) | + (d->devfn << 8) | (addr & ~3); + pci_data_write(s, addr & 3, val, 1); +} + +static __attribute__((unused)) uint32_t pci_config_readl(PCIDevice *d, uint32_t addr) +{ + PCIBus *s = d->bus; + s->config_reg = 0x80000000 | (s->bus_num << 16) | + (d->devfn << 8) | addr; + return pci_data_read(s, 0, 4); +} + +static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr) +{ + PCIBus *s = d->bus; + s->config_reg = 0x80000000 | (s->bus_num << 16) | + (d->devfn << 8) | (addr & ~3); + return pci_data_read(s, addr & 3, 2); +} + +static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr) +{ + PCIBus *s = d->bus; + s->config_reg = 0x80000000 | (s->bus_num << 16) | + (d->devfn << 8) | (addr & ~3); + return pci_data_read(s, addr & 3, 1); +} + +static uint32_t pci_bios_io_addr; +static uint32_t pci_bios_mem_addr; +/* host irqs corresponding to PCI irqs A-D */ +static uint8_t pci_irqs[4] = { 11, 9, 11, 9 }; + +static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr) +{ + PCIIORegion *r; + uint16_t cmd; + uint32_t ofs; + + if ( region_num == PCI_ROM_SLOT ) { + ofs = 0x30; + }else{ + ofs = 0x10 + region_num * 4; + } + + pci_config_writel(d, ofs, addr); + r = &d->io_regions[region_num]; + + /* enable memory mappings */ + cmd = pci_config_readw(d, PCI_COMMAND); + if ( region_num == PCI_ROM_SLOT ) + cmd |= 2; + else if (r->type & PCI_ADDRESS_SPACE_IO) + cmd |= 1; + else + cmd |= 2; + pci_config_writew(d, PCI_COMMAND, cmd); +} + +static void pci_bios_init_device(PCIDevice *d) +{ + int class; + PCIIORegion *r; + uint32_t *paddr; + int i, pin, pic_irq, vendor_id, device_id; + + class = pci_config_readw(d, PCI_CLASS_DEVICE); + vendor_id = pci_config_readw(d, PCI_VENDOR_ID); + device_id = pci_config_readw(d, PCI_DEVICE_ID); + switch(class) { + case 0x0101: + if (vendor_id == 0x8086 && device_id == 0x7010) { + /* PIIX3 IDE */ + pci_config_writew(d, 0x40, 0x8000); // enable IDE0 + pci_config_writew(d, 0x42, 0x8000); // enable IDE1 + goto default_map; + } else { + /* IDE: we map it as in ISA mode */ + pci_set_io_region_addr(d, 0, 0x1f0); + pci_set_io_region_addr(d, 1, 0x3f4); + pci_set_io_region_addr(d, 2, 0x170); + pci_set_io_region_addr(d, 3, 0x374); + } + break; + case 0x0300: + if (vendor_id != 0x1234) + goto default_map; + /* VGA: map frame buffer to default Bochs VBE address */ + pci_set_io_region_addr(d, 0, 0xE0000000); + break; + case 0x0800: + /* PIC */ + vendor_id = pci_config_readw(d, PCI_VENDOR_ID); + device_id = pci_config_readw(d, PCI_DEVICE_ID); + if (vendor_id == 0x1014) { + /* IBM */ + if (device_id == 0x0046 || device_id == 0xFFFF) { + /* MPIC & MPIC2 */ + pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000); + } + } + break; + case 0xff00: + if (vendor_id == 0x0106b && + (device_id == 0x0017 || device_id == 0x0022)) { + /* macio bridge */ + pci_set_io_region_addr(d, 0, 0x80800000); + } + break; + default: + default_map: + /* default memory mappings */ + for(i = 0; i < PCI_NUM_REGIONS; i++) { + r = &d->io_regions[i]; + if (r->size) { + if (r->type & PCI_ADDRESS_SPACE_IO) + paddr = &pci_bios_io_addr; + else + paddr = &pci_bios_mem_addr; + *paddr = (*paddr + r->size - 1) & ~(r->size - 1); + pci_set_io_region_addr(d, i, *paddr); + *paddr += r->size; + } + } + break; + } + + /* map the interrupt */ + pin = pci_config_readb(d, PCI_INTERRUPT_PIN); + if (pin != 0) { + pin = pci_slot_get_pirq(d, pin - 1); + pic_irq = pci_irqs[pin]; + pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq); + } +} + +/* + * This function initializes the PCI devices as a normal PCI BIOS + * would do. It is provided just in case the BIOS has no support for + * PCI. + */ +void pci_bios_init(void) +{ + PCIBus *bus; + PCIDevice *d; + int devfn, i, irq; + uint8_t elcr[2]; + + pci_bios_io_addr = 0xc000; + pci_bios_mem_addr = 0xf0000000; + + /* activate IRQ mappings */ + elcr[0] = 0x00; + elcr[1] = 0x00; + for(i = 0; i < 4; i++) { + irq = pci_irqs[i]; + /* set to trigger level */ + elcr[irq >> 3] |= (1 << (irq & 7)); + /* activate irq remapping in PIIX */ + pci_config_writeb((PCIDevice *)piix3_state, 0x60 + i, irq); + } + isa_outb(elcr[0], 0x4d0); + isa_outb(elcr[1], 0x4d1); + + bus = first_bus; + if (bus) { + for(devfn = 0; devfn < 256; devfn++) { + d = bus->devices[devfn]; + if (d) + pci_bios_init_device(d); + } + } +} diff --git a/tools/ioemu/hw/pckbd.c b/tools/ioemu/hw/pckbd.c new file mode 100644 index 0000000000..85863b433f --- /dev/null +++ b/tools/ioemu/hw/pckbd.c @@ -0,0 +1,919 @@ +/* + * QEMU PC keyboard emulation + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +/* debug PC keyboard */ +//#define DEBUG_KBD + +/* debug PC keyboard : only mouse */ +//#define DEBUG_MOUSE + +/* Keyboard Controller Commands */ +#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */ +#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */ +#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */ +#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */ +#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */ +#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */ +#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */ +#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */ +#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */ +#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */ +#define KBD_CCMD_READ_INPORT 0xC0 /* read input port */ +#define KBD_CCMD_READ_OUTPORT 0xD0 /* read output port */ +#define KBD_CCMD_WRITE_OUTPORT 0xD1 /* write output port */ +#define KBD_CCMD_WRITE_OBUF 0xD2 +#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if + initiated by the auxiliary device */ +#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */ +#define KBD_CCMD_DISABLE_A20 0xDD /* HP vectra only ? */ +#define KBD_CCMD_ENABLE_A20 0xDF /* HP vectra only ? */ +#define KBD_CCMD_RESET 0xFE + +/* Keyboard Commands */ +#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */ +#define KBD_CMD_ECHO 0xEE +#define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */ +#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */ +#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */ +#define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */ +#define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */ +#define KBD_CMD_RESET 0xFF /* Reset */ + +/* Keyboard Replies */ +#define KBD_REPLY_POR 0xAA /* Power on reset */ +#define KBD_REPLY_ACK 0xFA /* Command ACK */ +#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */ + +/* Status Register Bits */ +#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */ +#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */ +#define KBD_STAT_SELFTEST 0x04 /* Self test successful */ +#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */ +#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */ +#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */ +#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */ +#define KBD_STAT_PERR 0x80 /* Parity error */ + +/* Controller Mode Register Bits */ +#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */ +#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */ +#define KBD_MODE_SYS 0x04 /* The system flag (?) */ +#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */ +#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */ +#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */ +#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */ +#define KBD_MODE_RFU 0x80 + +/* Mouse Commands */ +#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */ +#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */ +#define AUX_SET_RES 0xE8 /* Set resolution */ +#define AUX_GET_SCALE 0xE9 /* Get scaling factor */ +/* according to Synaptic docs this $E9 is really 3-byte status */ +#define AUX_SET_STREAM 0xEA /* Set stream mode */ +#define AUX_POLL 0xEB /* Poll */ +#define AUX_RESET_WRAP 0xEC /* Reset wrap mode */ +#define AUX_SET_WRAP 0xEE /* Set wrap mode */ +#define AUX_SET_REMOTE 0xF0 /* Set remote mode */ +#define AUX_GET_TYPE 0xF2 /* Get type */ +#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */ +#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */ +#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */ +#define AUX_SET_DEFAULT 0xF6 +#define AUX_RESET 0xFF /* Reset aux device */ +#define AUX_ACK 0xFA /* Command byte ACK. */ + +#define MOUSE_STATUS_REMOTE 0x40 +#define MOUSE_STATUS_ENABLED 0x20 +#define MOUSE_STATUS_SCALE21 0x10 + +#define KBD_QUEUE_SIZE 256 + +typedef struct { + uint8_t aux[KBD_QUEUE_SIZE]; + uint8_t data[KBD_QUEUE_SIZE]; + int rptr, wptr, count; +} KBDQueue; + +typedef struct { + int absolute; + int high; +} TouchPad; + +typedef struct KBDState { + KBDQueue queue; + uint8_t write_cmd; /* if non zero, write data to port 60 is expected */ + uint8_t status; + uint8_t mode; + /* keyboard state */ + int kbd_write_cmd; + int scan_enabled; + /* mouse state */ + int mouse_write_cmd; + uint8_t mouse_status; + uint8_t mouse_resolution; + uint8_t mouse_sample_rate; + uint8_t mouse_wrap; + uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */ + uint8_t mouse_detect_state; + int mouse_dx; /* current values, needed for 'poll' mode */ + int mouse_dy; + int mouse_dz; + uint8_t mouse_buttons; + TouchPad touchpad; +} KBDState; + +KBDState kbd_state; + +/* update irq and KBD_STAT_[MOUSE_]OBF */ +/* XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be + incorrect, but it avoids having to simulate exact delays */ +static void kbd_update_irq(KBDState *s) +{ + KBDQueue *q = &s->queue; + int irq12_level, irq1_level; + + irq1_level = 0; + irq12_level = 0; + s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF); + if (q->count != 0) { + s->status |= KBD_STAT_OBF; + if (q->aux[q->rptr]) { + s->status |= KBD_STAT_MOUSE_OBF; + if (s->mode & KBD_MODE_MOUSE_INT) + irq12_level = 1; + } else { + if ((s->mode & KBD_MODE_KBD_INT) && + !(s->mode & KBD_MODE_DISABLE_KBD)) + irq1_level = 1; + } + } + pic_set_irq(1, irq1_level); + pic_set_irq(12, irq12_level); +} + +static void kbd_queue(KBDState *s, int b, int aux) +{ + KBDQueue *q = &s->queue; + +#if defined(DEBUG_MOUSE) || defined(DEBUG_KBD) + if (aux) + printf("mouse event: 0x%02x\n", b); +#ifdef DEBUG_KBD + else + printf("kbd event: 0x%02x\n", b); +#endif +#endif + if (q->count >= KBD_QUEUE_SIZE) + return; + q->aux[q->wptr] = aux; + q->data[q->wptr] = b; + if (++q->wptr == KBD_QUEUE_SIZE) + q->wptr = 0; + q->count++; + kbd_update_irq(s); +} + +static void pc_kbd_put_keycode(void *opaque, int keycode) +{ + KBDState *s = opaque; + kbd_queue(s, keycode, 0); +} + +static uint32_t kbd_read_status(void *opaque, uint32_t addr) +{ + KBDState *s = opaque; + int val; + val = s->status; +#if defined(DEBUG_KBD) + printf("kbd: read status=0x%02x\n", val); +#endif + return val; +} + +static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val) +{ + KBDState *s = opaque; + +#ifdef DEBUG_KBD + printf("kbd: write cmd=0x%02x\n", val); +#endif + switch(val) { + case KBD_CCMD_READ_MODE: + kbd_queue(s, s->mode, 0); + break; + case KBD_CCMD_WRITE_MODE: + case KBD_CCMD_WRITE_OBUF: + case KBD_CCMD_WRITE_AUX_OBUF: + case KBD_CCMD_WRITE_MOUSE: + case KBD_CCMD_WRITE_OUTPORT: + s->write_cmd = val; + break; + case KBD_CCMD_MOUSE_DISABLE: + s->mode |= KBD_MODE_DISABLE_MOUSE; + break; + case KBD_CCMD_MOUSE_ENABLE: + s->mode &= ~KBD_MODE_DISABLE_MOUSE; + break; + case KBD_CCMD_TEST_MOUSE: + kbd_queue(s, 0x00, 0); + break; + case KBD_CCMD_SELF_TEST: + s->status |= KBD_STAT_SELFTEST; + kbd_queue(s, 0x55, 0); + break; + case KBD_CCMD_KBD_TEST: + kbd_queue(s, 0x00, 0); + break; + case KBD_CCMD_KBD_DISABLE: + s->mode |= KBD_MODE_DISABLE_KBD; + kbd_update_irq(s); + break; + case KBD_CCMD_KBD_ENABLE: + s->mode &= ~KBD_MODE_DISABLE_KBD; + kbd_update_irq(s); + break; + case KBD_CCMD_READ_INPORT: + kbd_queue(s, 0x00, 0); + break; + case KBD_CCMD_READ_OUTPORT: + /* XXX: check that */ +#ifdef TARGET_I386 + val = 0x01 | (((cpu_single_env->a20_mask >> 20) & 1) << 1); +#else + val = 0x01; +#endif + if (s->status & KBD_STAT_OBF) + val |= 0x10; + if (s->status & KBD_STAT_MOUSE_OBF) + val |= 0x20; + kbd_queue(s, val, 0); + break; +#ifdef TARGET_I386 + case KBD_CCMD_ENABLE_A20: + cpu_x86_set_a20(cpu_single_env, 1); + break; + case KBD_CCMD_DISABLE_A20: + cpu_x86_set_a20(cpu_single_env, 0); + break; +#endif + case KBD_CCMD_RESET: + qemu_system_reset_request(); + break; + case 0xff: + /* ignore that - I don't know what is its use */ + break; + default: + fprintf(stderr, "qemu: unsupported keyboard cmd=0x%02x\n", val); + break; + } +} + +static uint32_t kbd_read_data(void *opaque, uint32_t addr) +{ + KBDState *s = opaque; + KBDQueue *q; + int val, index, aux; + + q = &s->queue; + if (q->count == 0) { + /* NOTE: if no data left, we return the last keyboard one + (needed for EMM386) */ + /* XXX: need a timer to do things correctly */ + index = q->rptr - 1; + if (index < 0) + index = KBD_QUEUE_SIZE - 1; + val = q->data[index]; + } else { + aux = q->aux[q->rptr]; + val = q->data[q->rptr]; + if (++q->rptr == KBD_QUEUE_SIZE) + q->rptr = 0; + q->count--; + /* reading deasserts IRQ */ + if (aux) + pic_set_irq(12, 0); + else + pic_set_irq(1, 0); + } + /* reassert IRQs if data left */ + kbd_update_irq(s); +#ifdef DEBUG_KBD + printf("kbd: read data=0x%02x\n", val); +#endif + return val; +} + +static void kbd_reset_keyboard(KBDState *s) +{ + s->scan_enabled = 1; +} + +static void kbd_write_keyboard(KBDState *s, int val) +{ + switch(s->kbd_write_cmd) { + default: + case -1: + switch(val) { + case 0x00: + kbd_queue(s, KBD_REPLY_ACK, 0); + break; + case 0x05: + kbd_queue(s, KBD_REPLY_RESEND, 0); + break; + case KBD_CMD_GET_ID: + kbd_queue(s, KBD_REPLY_ACK, 0); + kbd_queue(s, 0xab, 0); + kbd_queue(s, 0x83, 0); + break; + case KBD_CMD_ECHO: + kbd_queue(s, KBD_CMD_ECHO, 0); + break; + case KBD_CMD_ENABLE: + s->scan_enabled = 1; + kbd_queue(s, KBD_REPLY_ACK, 0); + break; + case KBD_CMD_SET_LEDS: + case KBD_CMD_SET_RATE: + s->kbd_write_cmd = val; + kbd_queue(s, KBD_REPLY_ACK, 0); + break; + case KBD_CMD_RESET_DISABLE: + kbd_reset_keyboard(s); + s->scan_enabled = 0; + kbd_queue(s, KBD_REPLY_ACK, 0); + break; + case KBD_CMD_RESET_ENABLE: + kbd_reset_keyboard(s); + s->scan_enabled = 1; + kbd_queue(s, KBD_REPLY_ACK, 0); + break; + case KBD_CMD_RESET: + kbd_reset_keyboard(s); + kbd_queue(s, KBD_REPLY_ACK, 0); + kbd_queue(s, KBD_REPLY_POR, 0); + break; + default: + kbd_queue(s, KBD_REPLY_ACK, 0); + break; + } + break; + case KBD_CMD_SET_LEDS: + kbd_queue(s, KBD_REPLY_ACK, 0); + s->kbd_write_cmd = -1; + break; + case KBD_CMD_SET_RATE: + kbd_queue(s, KBD_REPLY_ACK, 0); + s->kbd_write_cmd = -1; + break; + } +} + +static void kbd_mouse_send_packet(KBDState *s) +{ + unsigned int b; + int dx1, dy1, dz1; + + dx1 = s->mouse_dx; + dy1 = s->mouse_dy; + dz1 = s->mouse_dz; + if (s->touchpad.absolute) + { + int dz2, dleftnright, dg, df; + if (dx1 > 6143) + dx1 = 6143; + else if (dx1 < 0) + dx1 = 0; + if (dy1 > 6143) + dy1 = 6143; + else if (dy1 < 0) + dy1 = 0; + dz2 = 80; /* normal finger pressure */ + dg = 0; /* guesture not supported */ + df = 0; /* finger not supported */ + dleftnright = (s->mouse_buttons & 0x07); + /* + X: 13 bits --return absolute x ord + Y: 13 bits --return absolute y ord + Z: 8 bits --return constant 80 since we don't know how hard the user + is pressing on the mouse button ;) 80 is the default for pen + pressure, as touchpads cant sense what pressure a pen makes. + W: 4 bits --return 0, we don't support finger width (should we?) + left: 1 bit --is left button pressed + right: 1 bit --is right button pressed + guesture: 1 bit --we dont support, return 0 + finger: 1 bit --ditto + total: 42 bits in 6 bytes + note that Synaptics drivers ignore the finger and guesture bits and + consider them redundant + */ + /* + note: the packet setup is different when Wmode = 1, but + this doesn't apply since we don't support Wmode capability + format of packet is as follows: + */ + // 1 0 finger reserved 0 gesture right left + kbd_queue(s, (0x80 | (df ? 0x20 : 0) | (dg ? 0x04 : 0) | dleftnright), 1); + kbd_queue(s, ((dy1 & 0xF) * 256) + (dx1 & 0xF), 1); + kbd_queue(s, 80, 1); //byte 3 + // 1 1 y-12 x-12 0 gesture right left + kbd_queue(s, (0xC0 | ((dy1 & 1000) ? 0x20 : 0) | ((dx1 & 1000) ? 0x10 : 0) | (dg ? 0x04 : 0) | dleftnright), 1); + kbd_queue(s, dx1 & 0xFF, 1); + kbd_queue(s, dy1 & 0xFF, 1); + return; + } + /* XXX: increase range to 8 bits ? */ + if (dx1 > 127) + dx1 = 127; + else if (dx1 < -127) + dx1 = -127; + if (dy1 > 127) + dy1 = 127; + else if (dy1 < -127) + dy1 = -127; + b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07); + kbd_queue(s, b, 1); + kbd_queue(s, dx1 & 0xff, 1); + kbd_queue(s, dy1 & 0xff, 1); + /* extra byte for IMPS/2 or IMEX */ + switch(s->mouse_type) { + default: + break; + case 3: + if (dz1 > 127) + dz1 = 127; + else if (dz1 < -127) + dz1 = -127; + kbd_queue(s, dz1 & 0xff, 1); + break; + case 4: + if (dz1 > 7) + dz1 = 7; + else if (dz1 < -7) + dz1 = -7; + b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1); + kbd_queue(s, b, 1); + break; + } + + /* update deltas */ + s->mouse_dx -= dx1; + s->mouse_dy -= dy1; + s->mouse_dz -= dz1; +} + +static void pc_kbd_mouse_event(void *opaque, + int dx, int dy, int dz, int buttons_state) +{ + KBDState *s = opaque; + + /* check if deltas are recorded when disabled */ + if (!(s->mouse_status & MOUSE_STATUS_ENABLED)) + return; + + s->mouse_dx += dx; + s->mouse_dy -= dy; + s->mouse_dz += dz; + /* XXX: SDL sometimes generates nul events: we delete them */ + if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 && + s->mouse_buttons == buttons_state) + return; + s->mouse_buttons = buttons_state; + + if (!(s->mouse_status & MOUSE_STATUS_REMOTE) && + (s->queue.count < (KBD_QUEUE_SIZE - 16))) { + for(;;) { + /* if not remote, send event. Multiple events are sent if + too big deltas */ + kbd_mouse_send_packet(s); + if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0) + break; + } + } +} + +static void kbd_write_mouse(KBDState *s, int val) +{ +/* variables needed to store synaptics command info */ +static int rr = 0, ss = 0, tt = 0, uu = 0, res_count = 0, last_com = 0; +int spare; +#ifdef DEBUG_MOUSE + printf("kbd: write mouse 0x%02x\n", val); +#endif + switch(s->mouse_write_cmd) { + default: + case -1: + /* mouse command */ + if (s->mouse_wrap) { + if (val == AUX_RESET_WRAP) { + s->mouse_wrap = 0; + kbd_queue(s, AUX_ACK, 1); + return; + } else if (val != AUX_RESET) { + kbd_queue(s, val, 1); + return; + } + } + last_com = val; + switch(val) { + case AUX_SET_SCALE11: + s->mouse_status &= ~MOUSE_STATUS_SCALE21; + kbd_queue(s, AUX_ACK, 1); + break; + case AUX_SET_SCALE21: + s->mouse_status |= MOUSE_STATUS_SCALE21; + kbd_queue(s, AUX_ACK, 1); + break; + case AUX_SET_STREAM: + s->mouse_status &= ~MOUSE_STATUS_REMOTE; + kbd_queue(s, AUX_ACK, 1); + break; + case AUX_SET_WRAP: + s->mouse_wrap = 1; + kbd_queue(s, AUX_ACK, 1); + break; + case AUX_SET_REMOTE: + s->mouse_status |= MOUSE_STATUS_REMOTE; + kbd_queue(s, AUX_ACK, 1); + break; + case AUX_GET_TYPE: + kbd_queue(s, AUX_ACK, 1); + kbd_queue(s, s->mouse_type, 1); + break; + case AUX_SET_RES: + case AUX_SET_SAMPLE: + s->mouse_write_cmd = val; + kbd_queue(s, AUX_ACK, 1); + break; + case AUX_GET_SCALE: + if (res_count == 4) + { + /* time for the special stuff */ + kbd_queue(s, AUX_ACK, 1); + /* below is how we get the real synaptic command */ + val = (rr*64) + (ss*16) + (tt*4) + uu; + switch(val) + { + /* id touchpad */ + case 0x00: + /* info Minor */ + kbd_queue(s, 0x00, 1); + /* special verification byte */ + kbd_queue(s, 0x47, 1); + /* info Major * 0x10 + Info ModelCode*/ + kbd_queue(s, 4 * 0x10 + 0, 1); + break; + /* read touchpad modes */ + case 0x01: + /* special verification byte */ + kbd_queue(s, 0x3B, 1); + /* mode */ + /* + bit 7 - absolute or relative position + bit 6 - 0 for 40 packets/sec, 1 for 80 pack/sec + bit 3 - 1 for sleep mode, 0 for normal + bit 2 - 1 to detect tap/drag, 0 to disable + bit 1 - packet size, only valid for serial protocol + bit 0 - 0 for normal packets, 1 for enhanced packets + (absolute mode packets which have finger width) + */ + if (s->touchpad.absolute && s->touchpad.high) + { + spare = 0xC0; + } + else if (s->touchpad.absolute) + { + spare = 0x80; + } + else if (s->touchpad.high) + { + spare = 0x40; + } + else + { + spare = 0x00; + } + kbd_queue(s, spare, 1); + /* special verification byte */ + kbd_queue(s, 0x47, 1); + break; + /* read touchpad capabilites */ + case 0x02: + /* extended capability first 8 bits */ + kbd_queue(s, 0x00, 1); + /* special verification byte */ + kbd_queue(s, 0x47, 1); + /* extended capability last 8 bits */ + kbd_queue(s, 0x00, 1); + /* basicly, we don't have any capabilites ;0 */ + break; + /* read model id */ + case 0x03: + /* + bit 23 = 0 (1 for upsidedownpad) + bit 22 = 0 (1 for 90 degree rotated pad) + bits 21-16 = 1 (standard model) + bits 15-9 = ??? (reserved for synaptics use) + bit 7 = 1 + bit 6 = 0 (1 for sensing pens) + bit 5 = 1 + bits 3-0 = 1 (rectangular geometery) + */ + kbd_queue(s, 0xFC, 1); + kbd_queue(s, 0x00, 1); + kbd_queue(s, 0xF5, 1); //F7 for sensing pens + break; + /* read serial number prefix */ + case 0x06: + /* strange how they have this query even though + no touchpad actually has serial numbers */ + /* return serial prefix of 0 if we dont have one */ + kbd_queue(s, 0x00, 1); + kbd_queue(s, 0x00, 1); + kbd_queue(s, 0x00, 1); + break; + /* read serial number suffix */ + case 0x07: + /* undefined if we dont have a valid serial prefix */ + kbd_queue(s, 0x00, 1); + kbd_queue(s, 0x00, 1); + kbd_queue(s, 0x00, 1); + break; + /* read resolutions */ + case 0x08: + /* going to go with infoSensor = 1 (Standard model) here */ + /* absolute X in abolute units per mm */ + kbd_queue(s, 85, 1); + /* undefined but first bit 7 will be set to 1... + hell I'm going to set them all to 1 */ + kbd_queue(s, 0xFF, 1); + /* absolute Y in abolute units per mm */ + kbd_queue(s, 94, 1); + break; + default: + /* invalid commands return undefined data */ + kbd_queue(s, 0x00, 1); + kbd_queue(s, 0x00, 1); + kbd_queue(s, 0x00, 1); + break; + } + } + else + { + /* not a special command, just do the regular stuff */ + kbd_queue(s, AUX_ACK, 1); + kbd_queue(s, s->mouse_status, 1); + kbd_queue(s, s->mouse_resolution, 1); + kbd_queue(s, s->mouse_sample_rate, 1); + } + break; + case AUX_POLL: + kbd_queue(s, AUX_ACK, 1); + kbd_mouse_send_packet(s); + break; + case AUX_ENABLE_DEV: + s->mouse_status |= MOUSE_STATUS_ENABLED; + kbd_queue(s, AUX_ACK, 1); + break; + case AUX_DISABLE_DEV: + s->mouse_status &= ~MOUSE_STATUS_ENABLED; + kbd_queue(s, AUX_ACK, 1); + break; + case AUX_SET_DEFAULT: + s->mouse_sample_rate = 100; + s->mouse_resolution = 2; + s->mouse_status = 0; + s->touchpad.absolute = 0; + kbd_queue(s, AUX_ACK, 1); + break; + case AUX_RESET: + s->mouse_sample_rate = 100; + s->mouse_resolution = 2; + s->mouse_status = 0; + s->touchpad.absolute = 0; + kbd_queue(s, AUX_ACK, 1); + kbd_queue(s, 0xaa, 1); + kbd_queue(s, s->mouse_type, 1); + break; + default: + break; + } + break; + case AUX_SET_SAMPLE: + if (res_count == 4 && val == 0x14) + { + /* time for the special stuff */ + /* below is how we get the real synaptic command */ + val = (rr*64) + (ss*16) + (tt*4) + uu; + /* TODO: set the mode byte */ + } else + s->mouse_sample_rate = val; +#if 0 + /* detect IMPS/2 or IMEX */ + switch(s->mouse_detect_state) { + default: + case 0: + if (val == 200) + s->mouse_detect_state = 1; + break; + case 1: + if (val == 100) + s->mouse_detect_state = 2; + else if (val == 200) + s->mouse_detect_state = 3; + else + s->mouse_detect_state = 0; + break; + case 2: + if (val == 80) + s->mouse_type = 3; /* IMPS/2 */ + s->mouse_detect_state = 0; + break; + case 3: + if (val == 80) + s->mouse_type = 4; /* IMEX */ + s->mouse_detect_state = 0; + break; + } +#endif + kbd_queue(s, AUX_ACK, 1); + s->mouse_write_cmd = -1; + break; + case AUX_SET_RES: + if (last_com != AUX_SET_RES) + { + /* if its not 4 in a row, its not a command */ + /* FIXME: if we are set 8 of these in a row, or 12, or 16, + or etc ... or 4^n commands, then the nth'd mode byte sent might + still work. not sure if this is how things are suppose to be + or not. */ + res_count = 0; + } + res_count++; + if (res_count > 4) res_count = 4; + switch(res_count) + /* we need to save the val in the right spots to get the + real command later */ + { + case 1: + break; + rr = val; + case 2: + ss = val; + break; + case 3: + tt = val; + break; + case 4: + uu = val; + break; + } + s->mouse_resolution = val; + kbd_queue(s, AUX_ACK, 1); + s->mouse_write_cmd = -1; + break; + } +} + +void kbd_write_data(void *opaque, uint32_t addr, uint32_t val) +{ + KBDState *s = opaque; + +#ifdef DEBUG_KBD + printf("kbd: write data=0x%02x\n", val); +#endif + + switch(s->write_cmd) { + case 0: + kbd_write_keyboard(s, val); + break; + case KBD_CCMD_WRITE_MODE: + s->mode = val; + kbd_update_irq(s); + break; + case KBD_CCMD_WRITE_OBUF: + kbd_queue(s, val, 0); + break; + case KBD_CCMD_WRITE_AUX_OBUF: + kbd_queue(s, val, 1); + break; + case KBD_CCMD_WRITE_OUTPORT: +#ifdef TARGET_I386 + cpu_x86_set_a20(cpu_single_env, (val >> 1) & 1); +#endif + if (!(val & 1)) { + qemu_system_reset_request(); + } + break; + case KBD_CCMD_WRITE_MOUSE: + kbd_write_mouse(s, val); + break; + default: + break; + } + s->write_cmd = 0; +} + +static void kbd_reset(void *opaque) +{ + KBDState *s = opaque; + KBDQueue *q; + + s->kbd_write_cmd = -1; + s->mouse_write_cmd = -1; + s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT | KBD_MODE_KCC; + s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED; + q = &s->queue; + q->rptr = 0; + q->wptr = 0; + q->count = 0; +} + +static void kbd_save(QEMUFile* f, void* opaque) +{ + KBDState *s = (KBDState*)opaque; + + qemu_put_8s(f, &s->write_cmd); + qemu_put_8s(f, &s->status); + qemu_put_8s(f, &s->mode); + qemu_put_be32s(f, &s->kbd_write_cmd); + qemu_put_be32s(f, &s->scan_enabled); + qemu_put_be32s(f, &s->mouse_write_cmd); + qemu_put_8s(f, &s->mouse_status); + qemu_put_8s(f, &s->mouse_resolution); + qemu_put_8s(f, &s->mouse_sample_rate); + qemu_put_8s(f, &s->mouse_wrap); + qemu_put_8s(f, &s->mouse_type); + qemu_put_8s(f, &s->mouse_detect_state); + qemu_put_be32s(f, &s->mouse_dx); + qemu_put_be32s(f, &s->mouse_dy); + qemu_put_be32s(f, &s->mouse_dz); + qemu_put_8s(f, &s->mouse_buttons); + qemu_put_be32s(f, &s->touchpad.absolute); + qemu_put_be32s(f, &s->touchpad.high); +} + +static int kbd_load(QEMUFile* f, void* opaque, int version_id) +{ + KBDState *s = (KBDState*)opaque; + + if (version_id != 2) + return -EINVAL; + qemu_get_8s(f, &s->write_cmd); + qemu_get_8s(f, &s->status); + qemu_get_8s(f, &s->mode); + qemu_get_be32s(f, &s->kbd_write_cmd); + qemu_get_be32s(f, &s->scan_enabled); + qemu_get_be32s(f, &s->mouse_write_cmd); + qemu_get_8s(f, &s->mouse_status); + qemu_get_8s(f, &s->mouse_resolution); + qemu_get_8s(f, &s->mouse_sample_rate); + qemu_get_8s(f, &s->mouse_wrap); + qemu_get_8s(f, &s->mouse_type); + qemu_get_8s(f, &s->mouse_detect_state); + qemu_get_be32s(f, &s->mouse_dx); + qemu_get_be32s(f, &s->mouse_dy); + qemu_get_be32s(f, &s->mouse_dz); + qemu_get_8s(f, &s->mouse_buttons); + qemu_get_be32s(f, &s->touchpad.absolute); + qemu_get_be32s(f, &s->touchpad.high); + return 0; +} + +void kbd_init(void) +{ + KBDState *s = &kbd_state; + + kbd_reset(s); + register_savevm("pckbd", 0, 2, kbd_save, kbd_load, s); + register_ioport_read(0x60, 1, 1, kbd_read_data, s); + register_ioport_write(0x60, 1, 1, kbd_write_data, s); + register_ioport_read(0x64, 1, 1, kbd_read_status, s); + register_ioport_write(0x64, 1, 1, kbd_write_command, s); + + qemu_add_kbd_event_handler(pc_kbd_put_keycode, s); + qemu_add_mouse_event_handler(pc_kbd_mouse_event, s); + qemu_register_reset(kbd_reset, s); +} diff --git a/tools/ioemu/hw/ppc.c b/tools/ioemu/hw/ppc.c new file mode 100644 index 0000000000..5f992290e4 --- /dev/null +++ b/tools/ioemu/hw/ppc.c @@ -0,0 +1,462 @@ +/* + * QEMU generic PPC hardware System Emulator + * + * Copyright (c) 2003-2004 Jocelyn Mayer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" +#include "m48t59.h" + +/*****************************************************************************/ +/* PPC time base and decrementer emulation */ +//#define DEBUG_TB + +struct ppc_tb_t { + /* Time base management */ + int64_t tb_offset; /* Compensation */ + uint32_t tb_freq; /* TB frequency */ + /* Decrementer management */ + uint64_t decr_next; /* Tick for next decr interrupt */ + struct QEMUTimer *decr_timer; +}; + +static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env) +{ + /* TB time in tb periods */ + return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset, + tb_env->tb_freq, ticks_per_sec); +} + +uint32_t cpu_ppc_load_tbl (CPUState *env) +{ + ppc_tb_t *tb_env = env->tb_env; + uint64_t tb; + + tb = cpu_ppc_get_tb(tb_env); +#ifdef DEBUG_TB + { + static int last_time; + int now; + now = time(NULL); + if (last_time != now) { + last_time = now; + printf("%s: tb=0x%016lx %d %08lx\n", + __func__, tb, now, tb_env->tb_offset); + } + } +#endif + + return tb & 0xFFFFFFFF; +} + +uint32_t cpu_ppc_load_tbu (CPUState *env) +{ + ppc_tb_t *tb_env = env->tb_env; + uint64_t tb; + + tb = cpu_ppc_get_tb(tb_env); +#ifdef DEBUG_TB + printf("%s: tb=0x%016lx\n", __func__, tb); +#endif + return tb >> 32; +} + +static void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t value) +{ + tb_env->tb_offset = muldiv64(value, ticks_per_sec, tb_env->tb_freq) + - qemu_get_clock(vm_clock); +#ifdef DEBUG_TB + printf("%s: tb=0x%016lx offset=%08x\n", __func__, value); +#endif +} + +void cpu_ppc_store_tbu (CPUState *env, uint32_t value) +{ + ppc_tb_t *tb_env = env->tb_env; + + cpu_ppc_store_tb(tb_env, + ((uint64_t)value << 32) | cpu_ppc_load_tbl(env)); +} + +void cpu_ppc_store_tbl (CPUState *env, uint32_t value) +{ + ppc_tb_t *tb_env = env->tb_env; + + cpu_ppc_store_tb(tb_env, + ((uint64_t)cpu_ppc_load_tbu(env) << 32) | value); +} + +uint32_t cpu_ppc_load_decr (CPUState *env) +{ + ppc_tb_t *tb_env = env->tb_env; + uint32_t decr; + + decr = muldiv64(tb_env->decr_next - qemu_get_clock(vm_clock), + tb_env->tb_freq, ticks_per_sec); +#if defined(DEBUG_TB) + printf("%s: 0x%08x\n", __func__, decr); +#endif + + return decr; +} + +/* When decrementer expires, + * all we need to do is generate or queue a CPU exception + */ +static inline void cpu_ppc_decr_excp (CPUState *env) +{ + /* Raise it */ +#ifdef DEBUG_TB + printf("raise decrementer exception\n"); +#endif + cpu_interrupt(env, CPU_INTERRUPT_TIMER); +} + +static void _cpu_ppc_store_decr (CPUState *env, uint32_t decr, + uint32_t value, int is_excp) +{ + ppc_tb_t *tb_env = env->tb_env; + uint64_t now, next; + +#ifdef DEBUG_TB + printf("%s: 0x%08x => 0x%08x\n", __func__, decr, value); +#endif + now = qemu_get_clock(vm_clock); + next = now + muldiv64(value, ticks_per_sec, tb_env->tb_freq); + if (is_excp) + next += tb_env->decr_next - now; + if (next == now) + next++; + tb_env->decr_next = next; + /* Adjust timer */ + qemu_mod_timer(tb_env->decr_timer, next); + /* If we set a negative value and the decrementer was positive, + * raise an exception. + */ + if ((value & 0x80000000) && !(decr & 0x80000000)) + cpu_ppc_decr_excp(env); +} + +void cpu_ppc_store_decr (CPUState *env, uint32_t value) +{ + _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0); +} + +static void cpu_ppc_decr_cb (void *opaque) +{ + _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1); +} + +/* Set up (once) timebase frequency (in Hz) */ +ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq) +{ + ppc_tb_t *tb_env; + + tb_env = qemu_mallocz(sizeof(ppc_tb_t)); + if (tb_env == NULL) + return NULL; + env->tb_env = tb_env; + if (tb_env->tb_freq == 0 || 1) { + tb_env->tb_freq = freq; + /* Create new timer */ + tb_env->decr_timer = + qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env); + /* There is a bug in 2.4 kernels: + * if a decrementer exception is pending when it enables msr_ee, + * it's not ready to handle it... + */ + _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0); + } + + return tb_env; +} + +#if 0 +/*****************************************************************************/ +/* Handle system reset (for now, just stop emulation) */ +void cpu_ppc_reset (CPUState *env) +{ + printf("Reset asked... Stop emulation\n"); + abort(); +} +#endif + +static void PPC_io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) +{ + cpu_outb(NULL, addr & 0xffff, value); +} + +static uint32_t PPC_io_readb (void *opaque, target_phys_addr_t addr) +{ + uint32_t ret = cpu_inb(NULL, addr & 0xffff); + return ret; +} + +static void PPC_io_writew (void *opaque, target_phys_addr_t addr, uint32_t value) +{ +#ifdef TARGET_WORDS_BIGENDIAN + value = bswap16(value); +#endif + cpu_outw(NULL, addr & 0xffff, value); +} + +static uint32_t PPC_io_readw (void *opaque, target_phys_addr_t addr) +{ + uint32_t ret = cpu_inw(NULL, addr & 0xffff); +#ifdef TARGET_WORDS_BIGENDIAN + ret = bswap16(ret); +#endif + return ret; +} + +static void PPC_io_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +{ +#ifdef TARGET_WORDS_BIGENDIAN + value = bswap32(value); +#endif + cpu_outl(NULL, addr & 0xffff, value); +} + +static uint32_t PPC_io_readl (void *opaque, target_phys_addr_t addr) +{ + uint32_t ret = cpu_inl(NULL, addr & 0xffff); + +#ifdef TARGET_WORDS_BIGENDIAN + ret = bswap32(ret); +#endif + return ret; +} + +CPUWriteMemoryFunc *PPC_io_write[] = { + &PPC_io_writeb, + &PPC_io_writew, + &PPC_io_writel, +}; + +CPUReadMemoryFunc *PPC_io_read[] = { + &PPC_io_readb, + &PPC_io_readw, + &PPC_io_readl, +}; + +/*****************************************************************************/ +/* Debug port */ +void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val) +{ + addr &= 0xF; + switch (addr) { + case 0: + printf("%c", val); + break; + case 1: + printf("\n"); + fflush(stdout); + break; + case 2: + printf("Set loglevel to %04x\n", val); + cpu_set_log(val | 0x100); + break; + } +} + +/*****************************************************************************/ +/* NVRAM helpers */ +void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value) +{ + m48t59_set_addr(nvram, addr); + m48t59_write(nvram, value); +} + +uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr) +{ + m48t59_set_addr(nvram, addr); + return m48t59_read(nvram); +} + +void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value) +{ + m48t59_set_addr(nvram, addr); + m48t59_write(nvram, value >> 8); + m48t59_set_addr(nvram, addr + 1); + m48t59_write(nvram, value & 0xFF); +} + +uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr) +{ + uint16_t tmp; + + m48t59_set_addr(nvram, addr); + tmp = m48t59_read(nvram) << 8; + m48t59_set_addr(nvram, addr + 1); + tmp |= m48t59_read(nvram); + + return tmp; +} + +void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value) +{ + m48t59_set_addr(nvram, addr); + m48t59_write(nvram, value >> 24); + m48t59_set_addr(nvram, addr + 1); + m48t59_write(nvram, (value >> 16) & 0xFF); + m48t59_set_addr(nvram, addr + 2); + m48t59_write(nvram, (value >> 8) & 0xFF); + m48t59_set_addr(nvram, addr + 3); + m48t59_write(nvram, value & 0xFF); +} + +uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr) +{ + uint32_t tmp; + + m48t59_set_addr(nvram, addr); + tmp = m48t59_read(nvram) << 24; + m48t59_set_addr(nvram, addr + 1); + tmp |= m48t59_read(nvram) << 16; + m48t59_set_addr(nvram, addr + 2); + tmp |= m48t59_read(nvram) << 8; + m48t59_set_addr(nvram, addr + 3); + tmp |= m48t59_read(nvram); + + return tmp; +} + +void NVRAM_set_string (m48t59_t *nvram, uint32_t addr, + const unsigned char *str, uint32_t max) +{ + int i; + + for (i = 0; i < max && str[i] != '\0'; i++) { + m48t59_set_addr(nvram, addr + i); + m48t59_write(nvram, str[i]); + } + m48t59_set_addr(nvram, addr + max - 1); + m48t59_write(nvram, '\0'); +} + +int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max) +{ + int i; + + memset(dst, 0, max); + for (i = 0; i < max; i++) { + dst[i] = NVRAM_get_byte(nvram, addr + i); + if (dst[i] == '\0') + break; + } + + return i; +} + +static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value) +{ + uint16_t tmp; + uint16_t pd, pd1, pd2; + + tmp = prev >> 8; + pd = prev ^ value; + pd1 = pd & 0x000F; + pd2 = ((pd >> 4) & 0x000F) ^ pd1; + tmp ^= (pd1 << 3) | (pd1 << 8); + tmp ^= pd2 | (pd2 << 7) | (pd2 << 12); + + return tmp; +} + +uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count) +{ + uint32_t i; + uint16_t crc = 0xFFFF; + int odd; + + odd = count & 1; + count &= ~1; + for (i = 0; i != count; i++) { + crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i)); + } + if (odd) { + crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8); + } + + return crc; +} + +#define CMDLINE_ADDR 0x017ff000 + +int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size, + const unsigned char *arch, + uint32_t RAM_size, int boot_device, + uint32_t kernel_image, uint32_t kernel_size, + const char *cmdline, + uint32_t initrd_image, uint32_t initrd_size, + uint32_t NVRAM_image, + int width, int height, int depth) +{ + uint16_t crc; + + /* Set parameters for Open Hack'Ware BIOS */ + NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16); + NVRAM_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */ + NVRAM_set_word(nvram, 0x14, NVRAM_size); + NVRAM_set_string(nvram, 0x20, arch, 16); + NVRAM_set_lword(nvram, 0x30, RAM_size); + NVRAM_set_byte(nvram, 0x34, boot_device); + NVRAM_set_lword(nvram, 0x38, kernel_image); + NVRAM_set_lword(nvram, 0x3C, kernel_size); + if (cmdline) { + /* XXX: put the cmdline in NVRAM too ? */ + strcpy(phys_ram_base + CMDLINE_ADDR, cmdline); + NVRAM_set_lword(nvram, 0x40, CMDLINE_ADDR); + NVRAM_set_lword(nvram, 0x44, strlen(cmdline)); + } else { + NVRAM_set_lword(nvram, 0x40, 0); + NVRAM_set_lword(nvram, 0x44, 0); + } + NVRAM_set_lword(nvram, 0x48, initrd_image); + NVRAM_set_lword(nvram, 0x4C, initrd_size); + NVRAM_set_lword(nvram, 0x50, NVRAM_image); + + NVRAM_set_word(nvram, 0x54, width); + NVRAM_set_word(nvram, 0x56, height); + NVRAM_set_word(nvram, 0x58, depth); + crc = NVRAM_compute_crc(nvram, 0x00, 0xF8); + NVRAM_set_word(nvram, 0xFC, crc); + + return 0; + } + +/*****************************************************************************/ +void ppc_init (int ram_size, int vga_ram_size, int boot_device, + DisplayState *ds, const char **fd_filename, int snapshot, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename) +{ + if (prep_enabled) { + ppc_prep_init(ram_size, vga_ram_size, boot_device, ds, fd_filename, + snapshot, kernel_filename, kernel_cmdline, + initrd_filename); + } else { + ppc_chrp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename, + snapshot, kernel_filename, kernel_cmdline, + initrd_filename); + } + /* Special port to get debug messages from Open-Firmware */ + register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL); +} diff --git a/tools/ioemu/hw/ppc_chrp.c b/tools/ioemu/hw/ppc_chrp.c new file mode 100644 index 0000000000..cf3a5f32fa --- /dev/null +++ b/tools/ioemu/hw/ppc_chrp.c @@ -0,0 +1,233 @@ +/* + * QEMU PPC CHRP/PMAC hardware System Emulator + * + * Copyright (c) 2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +#define BIOS_FILENAME "ppc_rom.bin" +#define NVRAM_SIZE 0x2000 + +#define KERNEL_LOAD_ADDR 0x01000000 +#define INITRD_LOAD_ADDR 0x01800000 + +/* MacIO devices (mapped inside the MacIO address space): CUDA, DBDMA, + NVRAM (not implemented). */ + +static int dbdma_mem_index; +static int cuda_mem_index; +static int ide0_mem_index; +static int ide1_mem_index; +static int openpic_mem_index; + +/* DBDMA: currently no op - should suffice right now */ + +static void dbdma_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) +{ + printf("%s: 0x%08x <= 0x%08x\n", __func__, addr, value); +} + +static void dbdma_writew (void *opaque, target_phys_addr_t addr, uint32_t value) +{ +} + +static void dbdma_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +{ +} + +static uint32_t dbdma_readb (void *opaque, target_phys_addr_t addr) +{ + printf("%s: 0x%08x => 0x00000000\n", __func__, addr); + return 0; +} + +static uint32_t dbdma_readw (void *opaque, target_phys_addr_t addr) +{ + return 0; +} + +static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr) +{ + return 0; +} + +static CPUWriteMemoryFunc *dbdma_write[] = { + &dbdma_writeb, + &dbdma_writew, + &dbdma_writel, +}; + +static CPUReadMemoryFunc *dbdma_read[] = { + &dbdma_readb, + &dbdma_readw, + &dbdma_readl, +}; + +static void macio_map(PCIDevice *pci_dev, int region_num, + uint32_t addr, uint32_t size, int type) +{ + cpu_register_physical_memory(addr + 0x08000, 0x1000, dbdma_mem_index); + cpu_register_physical_memory(addr + 0x16000, 0x2000, cuda_mem_index); + cpu_register_physical_memory(addr + 0x1f000, 0x1000, ide0_mem_index); + cpu_register_physical_memory(addr + 0x20000, 0x1000, ide1_mem_index); + cpu_register_physical_memory(addr + 0x40000, 0x40000, openpic_mem_index); +} + +static void macio_init(PCIBus *bus) +{ + PCIDevice *d; + + d = pci_register_device(bus, "macio", sizeof(PCIDevice), + -1, NULL, NULL); + /* Note: this code is strongly inspirated from the corresponding code + in PearPC */ + d->config[0x00] = 0x6b; // vendor_id + d->config[0x01] = 0x10; + d->config[0x02] = 0x22; + d->config[0x03] = 0x00; + + d->config[0x0a] = 0x00; // class_sub = pci2pci + d->config[0x0b] = 0xff; // class_base = bridge + d->config[0x0e] = 0x00; // header_type + + d->config[0x3d] = 0x01; // interrupt on pin 1 + + dbdma_mem_index = cpu_register_io_memory(0, dbdma_read, dbdma_write, NULL); + + pci_register_io_region(d, 0, 0x80000, + PCI_ADDRESS_SPACE_MEM, macio_map); +} + +/* PowerPC PREP hardware initialisation */ +void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device, + DisplayState *ds, const char **fd_filename, int snapshot, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename) +{ + char buf[1024]; + openpic_t *openpic; + m48t59_t *nvram; + int PPC_io_memory; + int ret, linux_boot, i; + unsigned long bios_offset; + uint32_t kernel_base, kernel_size, initrd_base, initrd_size; + PCIBus *pci_bus; + + linux_boot = (kernel_filename != NULL); + + /* allocate RAM */ + cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); + + /* allocate and load BIOS */ + bios_offset = ram_size + vga_ram_size; + snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME); + ret = load_image(buf, phys_ram_base + bios_offset); + if (ret != BIOS_SIZE) { + fprintf(stderr, "qemu: could not load PPC PREP bios '%s'\n", buf); + exit(1); + } + cpu_register_physical_memory((uint32_t)(-BIOS_SIZE), + BIOS_SIZE, bios_offset | IO_MEM_ROM); + cpu_single_env->nip = 0xfffffffc; + + if (linux_boot) { + kernel_base = KERNEL_LOAD_ADDR; + /* now we can load the kernel */ + kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base); + if (kernel_size < 0) { + fprintf(stderr, "qemu: could not load kernel '%s'\n", + kernel_filename); + exit(1); + } + /* load initrd */ + if (initrd_filename) { + initrd_base = INITRD_LOAD_ADDR; + initrd_size = load_image(initrd_filename, + phys_ram_base + initrd_base); + if (initrd_size < 0) { + fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", + initrd_filename); + exit(1); + } + } else { + initrd_base = 0; + initrd_size = 0; + } + boot_device = 'm'; + } else { + kernel_base = 0; + kernel_size = 0; + initrd_base = 0; + initrd_size = 0; + } + /* Register CPU as a 74x/75x */ + cpu_ppc_register(cpu_single_env, 0x00080000); + /* Set time-base frequency to 100 Mhz */ + cpu_ppc_tb_init(cpu_single_env, 100UL * 1000UL * 1000UL); + + isa_mem_base = 0x80000000; + pci_bus = pci_pmac_init(); + + /* Register 8 MB of ISA IO space */ + PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL); + cpu_register_physical_memory(0xF2000000, 0x00800000, PPC_io_memory); + + /* init basic PC hardware */ + vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size, + vga_ram_size); + openpic = openpic_init(NULL, &openpic_mem_index, 1); + pci_pmac_set_openpic(pci_bus, openpic); + + /* XXX: suppress that */ + pic_init(); + + /* XXX: use Mac Serial port */ + serial_init(0x3f8, 4, serial_hds[0]); + + for(i = 0; i < nb_nics; i++) { + pci_ne2000_init(pci_bus, &nd_table[i]); + } + + ide0_mem_index = pmac_ide_init(&bs_table[0], openpic, 0x13); + ide1_mem_index = pmac_ide_init(&bs_table[2], openpic, 0x13); + + /* cuda also initialize ADB */ + cuda_mem_index = cuda_init(openpic, 0x19); + + adb_kbd_init(&adb_bus); + adb_mouse_init(&adb_bus); + + macio_init(pci_bus); + + nvram = m48t59_init(8, 0xFFF04000, 0x0074, NVRAM_SIZE); + + if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8) + graphic_depth = 15; + + PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "CHRP", ram_size, boot_device, + kernel_base, kernel_size, + kernel_cmdline, + initrd_base, initrd_size, + /* XXX: need an option to load a NVRAM image */ + 0, + graphic_width, graphic_height, graphic_depth); + /* No PCI init: the BIOS will do it */ +} diff --git a/tools/ioemu/hw/ppc_prep.c b/tools/ioemu/hw/ppc_prep.c new file mode 100644 index 0000000000..c93b72faeb --- /dev/null +++ b/tools/ioemu/hw/ppc_prep.c @@ -0,0 +1,548 @@ +/* + * QEMU PPC PREP hardware System Emulator + * + * Copyright (c) 2003-2004 Jocelyn Mayer + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +//#define HARD_DEBUG_PPC_IO +//#define DEBUG_PPC_IO + +#define BIOS_FILENAME "ppc_rom.bin" +#define KERNEL_LOAD_ADDR 0x01000000 +#define INITRD_LOAD_ADDR 0x01800000 + +extern int loglevel; +extern FILE *logfile; + +#if defined (HARD_DEBUG_PPC_IO) && !defined (DEBUG_PPC_IO) +#define DEBUG_PPC_IO +#endif + +#if defined (HARD_DEBUG_PPC_IO) +#define PPC_IO_DPRINTF(fmt, args...) \ +do { \ + if (loglevel & CPU_LOG_IOPORT) { \ + fprintf(logfile, "%s: " fmt, __func__ , ##args); \ + } else { \ + printf("%s : " fmt, __func__ , ##args); \ + } \ +} while (0) +#elif defined (DEBUG_PPC_IO) +#define PPC_IO_DPRINTF(fmt, args...) \ +do { \ + if (loglevel & CPU_LOG_IOPORT) { \ + fprintf(logfile, "%s: " fmt, __func__ , ##args); \ + } \ +} while (0) +#else +#define PPC_IO_DPRINTF(fmt, args...) do { } while (0) +#endif + +/* Constants for devices init */ +static const int ide_iobase[2] = { 0x1f0, 0x170 }; +static const int ide_iobase2[2] = { 0x3f6, 0x376 }; +static const int ide_irq[2] = { 13, 13 }; + +#define NE2000_NB_MAX 6 + +static uint32_t ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 }; +static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 }; + +//static PITState *pit; + +/* ISA IO ports bridge */ +#define PPC_IO_BASE 0x80000000 + +/* Speaker port 0x61 */ +int speaker_data_on; +int dummy_refresh_clock; + +static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ +#if 0 + speaker_data_on = (val >> 1) & 1; + pit_set_gate(pit, 2, val & 1); +#endif +} + +static uint32_t speaker_ioport_read(void *opaque, uint32_t addr) +{ +#if 0 + int out; + out = pit_get_out(pit, 2, qemu_get_clock(vm_clock)); + dummy_refresh_clock ^= 1; + return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) | + (dummy_refresh_clock << 4); +#endif + return 0; +} + +/* PCI intack register */ +/* Read-only register (?) */ +static void _PPC_intack_write (void *opaque, target_phys_addr_t addr, uint32_t value) +{ + // printf("%s: 0x%08x => 0x%08x\n", __func__, addr, value); +} + +static inline uint32_t _PPC_intack_read (target_phys_addr_t addr) +{ + uint32_t retval = 0; + + if (addr == 0xBFFFFFF0) + retval = pic_intack_read(NULL); + // printf("%s: 0x%08x <= %d\n", __func__, addr, retval); + + return retval; +} + +static uint32_t PPC_intack_readb (void *opaque, target_phys_addr_t addr) +{ + return _PPC_intack_read(addr); +} + +static uint32_t PPC_intack_readw (void *opaque, target_phys_addr_t addr) +{ +#ifdef TARGET_WORDS_BIGENDIAN + return bswap16(_PPC_intack_read(addr)); +#else + return _PPC_intack_read(addr); +#endif +} + +static uint32_t PPC_intack_readl (void *opaque, target_phys_addr_t addr) +{ +#ifdef TARGET_WORDS_BIGENDIAN + return bswap32(_PPC_intack_read(addr)); +#else + return _PPC_intack_read(addr); +#endif +} + +static CPUWriteMemoryFunc *PPC_intack_write[] = { + &_PPC_intack_write, + &_PPC_intack_write, + &_PPC_intack_write, +}; + +static CPUReadMemoryFunc *PPC_intack_read[] = { + &PPC_intack_readb, + &PPC_intack_readw, + &PPC_intack_readl, +}; + +/* PowerPC control and status registers */ +#if 0 // Not used +static struct { + /* IDs */ + uint32_t veni_devi; + uint32_t revi; + /* Control and status */ + uint32_t gcsr; + uint32_t xcfr; + uint32_t ct32; + uint32_t mcsr; + /* General purpose registers */ + uint32_t gprg[6]; + /* Exceptions */ + uint32_t feen; + uint32_t fest; + uint32_t fema; + uint32_t fecl; + uint32_t eeen; + uint32_t eest; + uint32_t eecl; + uint32_t eeint; + uint32_t eemck0; + uint32_t eemck1; + /* Error diagnostic */ +} XCSR; + +static void PPC_XCSR_writeb (void *opaque, target_phys_addr_t addr, uint32_t value) +{ + printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value); +} + +static void PPC_XCSR_writew (void *opaque, target_phys_addr_t addr, uint32_t value) +{ +#ifdef TARGET_WORDS_BIGENDIAN + value = bswap16(value); +#endif + printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value); +} + +static void PPC_XCSR_writel (void *opaque, target_phys_addr_t addr, uint32_t value) +{ +#ifdef TARGET_WORDS_BIGENDIAN + value = bswap32(value); +#endif + printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value); +} + +static uint32_t PPC_XCSR_readb (void *opaque, target_phys_addr_t addr) +{ + uint32_t retval = 0; + + printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval); + + return retval; +} + +static uint32_t PPC_XCSR_readw (void *opaque, target_phys_addr_t addr) +{ + uint32_t retval = 0; + + printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval); +#ifdef TARGET_WORDS_BIGENDIAN + retval = bswap16(retval); +#endif + + return retval; +} + +static uint32_t PPC_XCSR_readl (void *opaque, target_phys_addr_t addr) +{ + uint32_t retval = 0; + + printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval); +#ifdef TARGET_WORDS_BIGENDIAN + retval = bswap32(retval); +#endif + + return retval; +} + +static CPUWriteMemoryFunc *PPC_XCSR_write[] = { + &PPC_XCSR_writeb, + &PPC_XCSR_writew, + &PPC_XCSR_writel, +}; + +static CPUReadMemoryFunc *PPC_XCSR_read[] = { + &PPC_XCSR_readb, + &PPC_XCSR_readw, + &PPC_XCSR_readl, +}; +#endif + +/* Fake super-io ports for PREP platform (Intel 82378ZB) */ +typedef struct sysctrl_t { + m48t59_t *nvram; + uint8_t state; + uint8_t syscontrol; + uint8_t fake_io[2]; +} sysctrl_t; + +enum { + STATE_HARDFILE = 0x01, +}; + +static sysctrl_t *sysctrl; + +static void PREP_io_write (void *opaque, uint32_t addr, uint32_t val) +{ + sysctrl_t *sysctrl = opaque; + + PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val); + sysctrl->fake_io[addr - 0x0398] = val; +} + +static uint32_t PREP_io_read (void *opaque, uint32_t addr) +{ + sysctrl_t *sysctrl = opaque; + + PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE, + sysctrl->fake_io[addr - 0x0398]); + return sysctrl->fake_io[addr - 0x0398]; +} + +static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val) +{ + sysctrl_t *sysctrl = opaque; + + PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val); + switch (addr) { + case 0x0092: + /* Special port 92 */ + /* Check soft reset asked */ + if (val & 0x01) { + // cpu_interrupt(cpu_single_env, CPU_INTERRUPT_RESET); + } + /* Check LE mode */ + if (val & 0x02) { + printf("Little Endian mode isn't supported (yet ?)\n"); + abort(); + } + break; + case 0x0800: + /* Motorola CPU configuration register : read-only */ + break; + case 0x0802: + /* Motorola base module feature register : read-only */ + break; + case 0x0803: + /* Motorola base module status register : read-only */ + break; + case 0x0808: + /* Hardfile light register */ + if (val & 1) + sysctrl->state |= STATE_HARDFILE; + else + sysctrl->state &= ~STATE_HARDFILE; + break; + case 0x0810: + /* Password protect 1 register */ + if (sysctrl->nvram != NULL) + m48t59_toggle_lock(sysctrl->nvram, 1); + break; + case 0x0812: + /* Password protect 2 register */ + if (sysctrl->nvram != NULL) + m48t59_toggle_lock(sysctrl->nvram, 2); + break; + case 0x0814: + /* L2 invalidate register */ + // tlb_flush(cpu_single_env, 1); + break; + case 0x081C: + /* system control register */ + sysctrl->syscontrol = val & 0x0F; + break; + case 0x0850: + /* I/O map type register */ + if (!(val & 0x01)) { + printf("No support for non-continuous I/O map mode\n"); + abort(); + } + break; + default: + printf("ERROR: unaffected IO port write: %04lx => %02x\n", + (long)addr, val); + break; + } +} + +static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr) +{ + sysctrl_t *sysctrl = opaque; + uint32_t retval = 0xFF; + + switch (addr) { + case 0x0092: + /* Special port 92 */ + retval = 0x00; + break; + case 0x0800: + /* Motorola CPU configuration register */ + retval = 0xEF; /* MPC750 */ + break; + case 0x0802: + /* Motorola Base module feature register */ + retval = 0xAD; /* No ESCC, PMC slot neither ethernet */ + break; + case 0x0803: + /* Motorola base module status register */ + retval = 0xE0; /* Standard MPC750 */ + break; + case 0x080C: + /* Equipment present register: + * no L2 cache + * no upgrade processor + * no cards in PCI slots + * SCSI fuse is bad + */ + retval = 0x3C; + break; + case 0x0810: + /* Motorola base module extended feature register */ + retval = 0x39; /* No USB, CF and PCI bridge. NVRAM present */ + break; + case 0x0818: + /* Keylock */ + retval = 0x00; + break; + case 0x081C: + /* system control register + * 7 - 6 / 1 - 0: L2 cache enable + */ + retval = sysctrl->syscontrol; + break; + case 0x0823: + /* */ + retval = 0x03; /* no L2 cache */ + break; + case 0x0850: + /* I/O map type register */ + retval = 0x01; + break; + default: + printf("ERROR: unaffected IO port: %04lx read\n", (long)addr); + break; + } + PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE, retval); + + return retval; +} + +extern CPUPPCState *global_env; + +#define NVRAM_SIZE 0x2000 + +/* PowerPC PREP hardware initialisation */ +void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device, + DisplayState *ds, const char **fd_filename, int snapshot, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename) +{ + char buf[1024]; + m48t59_t *nvram; + int PPC_io_memory; + int ret, linux_boot, i, nb_nics1; + unsigned long bios_offset; + uint32_t kernel_base, kernel_size, initrd_base, initrd_size; + PCIBus *pci_bus; + + sysctrl = qemu_mallocz(sizeof(sysctrl_t)); + if (sysctrl == NULL) + return; + + linux_boot = (kernel_filename != NULL); + + /* allocate RAM */ + cpu_register_physical_memory(0, ram_size, IO_MEM_RAM); + + /* allocate and load BIOS */ + bios_offset = ram_size + vga_ram_size; + snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME); + ret = load_image(buf, phys_ram_base + bios_offset); + if (ret != BIOS_SIZE) { + fprintf(stderr, "qemu: could not load PPC PREP bios '%s'\n", buf); + exit(1); + } + cpu_register_physical_memory((uint32_t)(-BIOS_SIZE), + BIOS_SIZE, bios_offset | IO_MEM_ROM); + cpu_single_env->nip = 0xfffffffc; + + if (linux_boot) { + kernel_base = KERNEL_LOAD_ADDR; + /* now we can load the kernel */ + kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base); + if (kernel_size < 0) { + fprintf(stderr, "qemu: could not load kernel '%s'\n", + kernel_filename); + exit(1); + } + /* load initrd */ + if (initrd_filename) { + initrd_base = INITRD_LOAD_ADDR; + initrd_size = load_image(initrd_filename, + phys_ram_base + initrd_base); + if (initrd_size < 0) { + fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", + initrd_filename); + exit(1); + } + } else { + initrd_base = 0; + initrd_size = 0; + } + boot_device = 'm'; + } else { + kernel_base = 0; + kernel_size = 0; + initrd_base = 0; + initrd_size = 0; + } + + /* Register CPU as a 74x/75x */ + cpu_ppc_register(cpu_single_env, 0x00080000); + /* Set time-base frequency to 100 Mhz */ + cpu_ppc_tb_init(cpu_single_env, 100UL * 1000UL * 1000UL); + + isa_mem_base = 0xc0000000; + pci_bus = pci_prep_init(); + /* Register 64 KB of ISA IO space */ + PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL); + cpu_register_physical_memory(0x80000000, 0x00010000, PPC_io_memory); + + /* init basic PC hardware */ + vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size, + vga_ram_size); + rtc_init(0x70, 8); + // openpic = openpic_init(0x00000000, 0xF0000000, 1); + // pic_init(openpic); + pic_init(); + // pit = pit_init(0x40, 0); + + serial_init(0x3f8, 4, serial_hds[0]); + nb_nics1 = nb_nics; + if (nb_nics1 > NE2000_NB_MAX) + nb_nics1 = NE2000_NB_MAX; + for(i = 0; i < nb_nics1; i++) { + isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]); + } + + for(i = 0; i < 2; i++) { + isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i], + bs_table[2 * i], bs_table[2 * i + 1]); + } + kbd_init(); + DMA_init(1); + // AUD_init(); + // SB16_init(); + + fdctrl_init(6, 2, 0, 0x3f0, fd_table); + + /* Register speaker port */ + register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL); + register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL); + /* Register fake IO ports for PREP */ + register_ioport_read(0x398, 2, 1, &PREP_io_read, sysctrl); + register_ioport_write(0x398, 2, 1, &PREP_io_write, sysctrl); + /* System control ports */ + register_ioport_read(0x0092, 0x01, 1, &PREP_io_800_readb, sysctrl); + register_ioport_write(0x0092, 0x01, 1, &PREP_io_800_writeb, sysctrl); + register_ioport_read(0x0800, 0x52, 1, &PREP_io_800_readb, sysctrl); + register_ioport_write(0x0800, 0x52, 1, &PREP_io_800_writeb, sysctrl); + /* PCI intack location */ + PPC_io_memory = cpu_register_io_memory(0, PPC_intack_read, + PPC_intack_write, NULL); + cpu_register_physical_memory(0xBFFFFFF0, 0x4, PPC_io_memory); + /* PowerPC control and status register group */ +#if 0 + PPC_io_memory = cpu_register_io_memory(0, PPC_XCSR_read, PPC_XCSR_write, NULL); + cpu_register_physical_memory(0xFEFF0000, 0x1000, PPC_io_memory); +#endif + + nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE); + if (nvram == NULL) + return; + sysctrl->nvram = nvram; + + /* Initialise NVRAM */ + PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "PREP", ram_size, boot_device, + kernel_base, kernel_size, + kernel_cmdline, + initrd_base, initrd_size, + /* XXX: need an option to load a NVRAM image */ + 0, + graphic_width, graphic_height, graphic_depth); +} diff --git a/tools/ioemu/hw/sb16.c b/tools/ioemu/hw/sb16.c new file mode 100644 index 0000000000..33026febb4 --- /dev/null +++ b/tools/ioemu/hw/sb16.c @@ -0,0 +1,1268 @@ +/* + * QEMU Soundblaster 16 emulation + * + * Copyright (c) 2003-2004 Vassili Karpov (malc) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0]))) + +#define dolog(...) AUD_log ("sb16", __VA_ARGS__) + +/* #define DEBUG */ +/* #define DEBUG_SB16_MOST */ + +#ifdef DEBUG +#define ldebug(...) dolog (__VA_ARGS__) +#else +#define ldebug(...) +#endif + +#define IO_READ_PROTO(name) \ + uint32_t name (void *opaque, uint32_t nport) +#define IO_WRITE_PROTO(name) \ + void name (void *opaque, uint32_t nport, uint32_t val) + +static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."; + +static struct { + int ver_lo; + int ver_hi; + int irq; + int dma; + int hdma; + int port; +} conf = {5, 4, 5, 1, 5, 0x220}; + +typedef struct SB16State { + int irq; + int dma; + int hdma; + int port; + int ver; + + int in_index; + int out_data_len; + int fmt_stereo; + int fmt_signed; + int fmt_bits; + audfmt_e fmt; + int dma_auto; + int block_size; + int fifo; + int freq; + int time_const; + int speaker; + int needed_bytes; + int cmd; + int use_hdma; + int highspeed; + int can_write; + + int v2x6; + + uint8_t csp_param; + uint8_t csp_value; + uint8_t csp_mode; + uint8_t csp_regs[256]; + uint8_t csp_index; + uint8_t csp_reg83[4]; + int csp_reg83r; + int csp_reg83w; + + uint8_t in2_data[10]; + uint8_t out_data[50]; + uint8_t test_reg; + uint8_t last_read_byte; + int nzero; + + int left_till_irq; + + int dma_running; + int bytes_per_second; + int align; + SWVoice *voice; + + QEMUTimer *ts, *aux_ts; + /* mixer state */ + int mixer_nreg; + uint8_t mixer_regs[256]; +} SB16State; + +/* XXX: suppress that and use a context */ +static struct SB16State dsp; + +static int magic_of_irq (int irq) +{ + switch (irq) { + case 5: + return 2; + case 7: + return 4; + case 9: + return 1; + case 10: + return 8; + default: + dolog ("bad irq %d\n", irq); + return 2; + } +} + +static int irq_of_magic (int magic) +{ + switch (magic) { + case 1: + return 9; + case 2: + return 5; + case 4: + return 7; + case 8: + return 10; + default: + dolog ("bad irq magic %d\n", magic); + return -1; + } +} + +#if 0 +static void log_dsp (SB16State *dsp) +{ + ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n", + dsp->fmt_stereo ? "Stereo" : "Mono", + dsp->fmt_signed ? "Signed" : "Unsigned", + dsp->fmt_bits, + dsp->dma_auto ? "Auto" : "Single", + dsp->block_size, + dsp->freq, + dsp->time_const, + dsp->speaker); +} +#endif + +static void speaker (SB16State *s, int on) +{ + s->speaker = on; + /* AUD_enable (s->voice, on); */ +} + +static void control (SB16State *s, int hold) +{ + int dma = s->use_hdma ? s->hdma : s->dma; + s->dma_running = hold; + + ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma); + + if (hold) { + DMA_hold_DREQ (dma); + AUD_enable (s->voice, 1); + } + else { + DMA_release_DREQ (dma); + AUD_enable (s->voice, 0); + } +} + +static void aux_timer (void *opaque) +{ + SB16State *s = opaque; + s->can_write = 1; + pic_set_irq (s->irq, 1); +} + +#define DMA8_AUTO 1 +#define DMA8_HIGH 2 + +static void dma_cmd8 (SB16State *s, int mask, int dma_len) +{ + s->fmt = AUD_FMT_U8; + s->use_hdma = 0; + s->fmt_bits = 8; + s->fmt_signed = 0; + s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0; + if (-1 == s->time_const) { + s->freq = 11025; + } + else { + int tmp = (256 - s->time_const); + s->freq = (1000000 + (tmp / 2)) / tmp; + } + + if (dma_len != -1) + s->block_size = dma_len << s->fmt_stereo; + else { + /* This is apparently the only way to make both Act1/PL + and SecondReality/FC work + + Act1 sets block size via command 0x48 and it's an odd number + SR does the same with even number + Both use stereo, and Creatives own documentation states that + 0x48 sets block size in bytes less one.. go figure */ + s->block_size &= ~s->fmt_stereo; + } + + s->freq >>= s->fmt_stereo; + s->left_till_irq = s->block_size; + s->bytes_per_second = (s->freq << s->fmt_stereo); + /* s->highspeed = (mask & DMA8_HIGH) != 0; */ + s->dma_auto = (mask & DMA8_AUTO) != 0; + s->align = (1 << s->fmt_stereo) - 1; + + if (s->block_size & s->align) + dolog ("warning: unaligned buffer\n"); + + ldebug ("freq %d, stereo %d, sign %d, bits %d, " + "dma %d, auto %d, fifo %d, high %d\n", + s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits, + s->block_size, s->dma_auto, s->fifo, s->highspeed); + + if (s->freq) + s->voice = AUD_open (s->voice, "sb16", s->freq, + 1 << s->fmt_stereo, s->fmt); + + control (s, 1); + speaker (s, 1); +} + +static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len) +{ + s->use_hdma = cmd < 0xc0; + s->fifo = (cmd >> 1) & 1; + s->dma_auto = (cmd >> 2) & 1; + s->fmt_signed = (d0 >> 4) & 1; + s->fmt_stereo = (d0 >> 5) & 1; + + switch (cmd >> 4) { + case 11: + s->fmt_bits = 16; + break; + + case 12: + s->fmt_bits = 8; + break; + } + + if (-1 != s->time_const) { +#if 1 + int tmp = 256 - s->time_const; + s->freq = (1000000 + (tmp / 2)) / tmp; +#else + /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */ + s->freq = 1000000 / ((255 - s->time_const)); +#endif + s->time_const = -1; + } + + s->block_size = dma_len + 1; + s->block_size <<= (s->fmt_bits == 16); + if (!s->dma_auto) { + /* It is clear that for DOOM and auto-init this value + shouldn't take stereo into account, while Miles Sound Systems + setsound.exe with single transfer mode wouldn't work without it + wonders of SB16 yet again */ + s->block_size <<= s->fmt_stereo; + } + + ldebug ("freq %d, stereo %d, sign %d, bits %d, " + "dma %d, auto %d, fifo %d, high %d\n", + s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits, + s->block_size, s->dma_auto, s->fifo, s->highspeed); + + if (16 == s->fmt_bits) { + if (s->fmt_signed) { + s->fmt = AUD_FMT_S16; + } + else { + s->fmt = AUD_FMT_U16; + } + } + else { + if (s->fmt_signed) { + s->fmt = AUD_FMT_S8; + } + else { + s->fmt = AUD_FMT_U8; + } + } + + s->left_till_irq = s->block_size; + + s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16); + s->highspeed = 0; + s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1; + if (s->block_size & s->align) + dolog ("warning: unaligned buffer\n"); + + if (s->freq) + s->voice = AUD_open (s->voice, "sb16", s->freq, + 1 << s->fmt_stereo, s->fmt); + + control (s, 1); + speaker (s, 1); +} + +static inline void dsp_out_data (SB16State *s, uint8_t val) +{ + ldebug ("outdata %#x\n", val); + if (s->out_data_len < sizeof (s->out_data)) + s->out_data[s->out_data_len++] = val; +} + +static inline uint8_t dsp_get_data (SB16State *s) +{ + if (s->in_index) + return s->in2_data[--s->in_index]; + else { + dolog ("buffer underflow\n"); + return 0; + } +} + +static void command (SB16State *s, uint8_t cmd) +{ + ldebug ("command %#x\n", cmd); + + if (cmd > 0xaf && cmd < 0xd0) { + if (cmd & 8) { + dolog ("ADC not yet supported (command %#x)\n", cmd); + } + + switch (cmd >> 4) { + case 11: + case 12: + break; + default: + dolog ("%#x wrong bits\n", cmd); + } + s->needed_bytes = 3; + } + else { + switch (cmd) { + case 0x03: + dsp_out_data (s, 0x10); /* s->csp_param); */ + goto warn; + + case 0x04: + s->needed_bytes = 1; + goto warn; + + case 0x05: + s->needed_bytes = 2; + goto warn; + + case 0x08: + /* __asm__ ("int3"); */ + goto warn; + + case 0x0e: + s->needed_bytes = 2; + goto warn; + + case 0x09: + dsp_out_data (s, 0xf8); + goto warn; + + case 0x0f: + s->needed_bytes = 1; + goto warn; + + case 0x10: + s->needed_bytes = 1; + goto warn; + + case 0x14: + s->needed_bytes = 2; + s->block_size = 0; + break; + + case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */ + control (s, 1); + break; + + case 0x20: /* Direct ADC, Juice/PL */ + dsp_out_data (s, 0xff); + goto warn; + + case 0x35: + dolog ("MIDI command(0x35) not implemented\n"); + break; + + case 0x40: + s->freq = -1; + s->time_const = -1; + s->needed_bytes = 1; + break; + + case 0x41: + s->freq = -1; + s->time_const = -1; + s->needed_bytes = 2; + break; + + case 0x42: + s->freq = -1; + s->time_const = -1; + s->needed_bytes = 2; + goto warn; + + case 0x45: + dsp_out_data (s, 0xaa); + goto warn; + + case 0x47: /* Continue Auto-Initialize DMA 16bit */ + break; + + case 0x48: + s->needed_bytes = 2; + break; + + case 0x80: + s->needed_bytes = 2; + break; + + case 0x90: + case 0x91: + dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1); + break; + + case 0xd0: /* halt DMA operation. 8bit */ + control (s, 0); + break; + + case 0xd1: /* speaker on */ + speaker (s, 1); + break; + + case 0xd3: /* speaker off */ + speaker (s, 0); + break; + + case 0xd4: /* continue DMA operation. 8bit */ + control (s, 1); + break; + + case 0xd5: /* halt DMA operation. 16bit */ + control (s, 0); + break; + + case 0xd6: /* continue DMA operation. 16bit */ + control (s, 1); + break; + + case 0xd9: /* exit auto-init DMA after this block. 16bit */ + s->dma_auto = 0; + break; + + case 0xda: /* exit auto-init DMA after this block. 8bit */ + s->dma_auto = 0; + break; + + case 0xe0: + s->needed_bytes = 1; + goto warn; + + case 0xe1: + dsp_out_data (s, s->ver & 0xff); + dsp_out_data (s, s->ver >> 8); + break; + + case 0xe2: + s->needed_bytes = 1; + goto warn; + + case 0xe3: + { + int i; + for (i = sizeof (e3) - 1; i >= 0; --i) + dsp_out_data (s, e3[i]); + } + break; + + case 0xe4: /* write test reg */ + s->needed_bytes = 1; + break; + + case 0xe7: + dolog ("Attempt to probe for ESS (0xe7)?\n"); + return; + + case 0xe8: /* read test reg */ + dsp_out_data (s, s->test_reg); + break; + + case 0xf2: + case 0xf3: + dsp_out_data (s, 0xaa); + s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2; + pic_set_irq (s->irq, 1); + break; + + case 0xf9: + s->needed_bytes = 1; + goto warn; + + case 0xfa: + dsp_out_data (s, 0); + goto warn; + + case 0xfc: /* FIXME */ + dsp_out_data (s, 0); + goto warn; + + default: + dolog ("unrecognized command %#x\n", cmd); + return; + } + } + + s->cmd = cmd; + if (!s->needed_bytes) + ldebug ("\n"); + return; + + warn: + dolog ("warning: command %#x,%d is not trully understood yet\n", + cmd, s->needed_bytes); + s->cmd = cmd; + return; +} + +static uint16_t dsp_get_lohi (SB16State *s) +{ + uint8_t hi = dsp_get_data (s); + uint8_t lo = dsp_get_data (s); + return (hi << 8) | lo; +} + +static uint16_t dsp_get_hilo (SB16State *s) +{ + uint8_t lo = dsp_get_data (s); + uint8_t hi = dsp_get_data (s); + return (hi << 8) | lo; +} + +static void complete (SB16State *s) +{ + int d0, d1, d2; + ldebug ("complete command %#x, in_index %d, needed_bytes %d\n", + s->cmd, s->in_index, s->needed_bytes); + + if (s->cmd > 0xaf && s->cmd < 0xd0) { + d2 = dsp_get_data (s); + d1 = dsp_get_data (s); + d0 = dsp_get_data (s); + + if (s->cmd & 8) { + dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n", + s->cmd, d0, d1, d2); + } + else { + ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n", + s->cmd, d0, d1, d2); + dma_cmd (s, s->cmd, d0, d1 + (d2 << 8)); + } + } + else { + switch (s->cmd) { + case 0x04: + s->csp_mode = dsp_get_data (s); + s->csp_reg83r = 0; + s->csp_reg83w = 0; + ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode); + break; + + case 0x05: + s->csp_param = dsp_get_data (s); + s->csp_value = dsp_get_data (s); + ldebug ("CSP command 0x05: param=%#x value=%#x\n", + s->csp_param, + s->csp_value); + break; + + case 0x0e: + d0 = dsp_get_data (s); + d1 = dsp_get_data (s); + ldebug ("write CSP register %d <- %#x\n", d1, d0); + if (d1 == 0x83) { + ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0); + s->csp_reg83[s->csp_reg83r % 4] = d0; + s->csp_reg83r += 1; + } + else + s->csp_regs[d1] = d0; + break; + + case 0x0f: + d0 = dsp_get_data (s); + ldebug ("read CSP register %#x -> %#x, mode=%#x\n", + d0, s->csp_regs[d0], s->csp_mode); + if (d0 == 0x83) { + ldebug ("0x83[%d] -> %#x\n", + s->csp_reg83w, + s->csp_reg83[s->csp_reg83w % 4]); + dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]); + s->csp_reg83w += 1; + } + else + dsp_out_data (s, s->csp_regs[d0]); + break; + + case 0x10: + d0 = dsp_get_data (s); + dolog ("cmd 0x10 d0=%#x\n", d0); + break; + + case 0x14: + dma_cmd8 (s, 0, dsp_get_lohi (s) + 1); + break; + + case 0x40: + s->time_const = dsp_get_data (s); + ldebug ("set time const %d\n", s->time_const); + break; + + case 0x42: /* FT2 sets output freq with this, go figure */ + dolog ("cmd 0x42 might not do what it think it should\n"); + + case 0x41: + s->freq = dsp_get_hilo (s); + ldebug ("set freq %d\n", s->freq); + break; + + case 0x48: + s->block_size = dsp_get_lohi (s) + 1; + ldebug ("set dma block len %d\n", s->block_size); + break; + + case 0x80: + { + int freq, samples, bytes; + int64_t ticks; + + freq = s->freq > 0 ? s->freq : 11025; + samples = dsp_get_lohi (s) + 1; + bytes = samples << s->fmt_stereo << (s->fmt_bits == 16); + ticks = (bytes * ticks_per_sec) / freq; + if (ticks < ticks_per_sec / 1024) + pic_set_irq (s->irq, 1); + else + qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks); + ldebug ("mix silence %d %d %lld\n", samples, bytes, ticks); + } + break; + + case 0xe0: + d0 = dsp_get_data (s); + s->out_data_len = 0; + ldebug ("E0 data = %#x\n", d0); + dsp_out_data(s, ~d0); + break; + + case 0xe2: + d0 = dsp_get_data (s); + ldebug ("E2 = %#x\n", d0); + break; + + case 0xe4: + s->test_reg = dsp_get_data (s); + break; + + case 0xf9: + d0 = dsp_get_data (s); + ldebug ("command 0xf9 with %#x\n", d0); + switch (d0) { + case 0x0e: + dsp_out_data (s, 0xff); + break; + + case 0x0f: + dsp_out_data (s, 0x07); + break; + + case 0x37: + dsp_out_data (s, 0x38); + break; + + default: + dsp_out_data (s, 0x00); + break; + } + break; + + default: + dolog ("complete: unrecognized command %#x\n", s->cmd); + return; + } + } + + ldebug ("\n"); + s->cmd = -1; + return; +} + +static void reset (SB16State *s) +{ + pic_set_irq (s->irq, 0); + if (s->dma_auto) { + pic_set_irq (s->irq, 1); + pic_set_irq (s->irq, 0); + } + + s->mixer_regs[0x82] = 0; + s->dma_auto = 0; + s->in_index = 0; + s->out_data_len = 0; + s->left_till_irq = 0; + s->needed_bytes = 0; + s->block_size = -1; + s->nzero = 0; + s->highspeed = 0; + s->v2x6 = 0; + + dsp_out_data(s, 0xaa); + speaker (s, 0); + control (s, 0); +} + +static IO_WRITE_PROTO (dsp_write) +{ + SB16State *s = opaque; + int iport; + + iport = nport - s->port; + + ldebug ("write %#x <- %#x\n", nport, val); + switch (iport) { + case 0x06: + switch (val) { + case 0x00: + if (s->v2x6 == 1) { + if (0 && s->highspeed) { + s->highspeed = 0; + pic_set_irq (s->irq, 0); + control (s, 0); + } + else + reset (s); + } + s->v2x6 = 0; + break; + + case 0x01: + case 0x03: /* FreeBSD kludge */ + s->v2x6 = 1; + break; + + case 0xc6: + s->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */ + break; + + case 0xb8: /* Panic */ + reset (s); + break; + + case 0x39: + dsp_out_data (s, 0x38); + reset (s); + s->v2x6 = 0x39; + break; + + default: + s->v2x6 = val; + break; + } + break; + + case 0x0c: /* write data or command | write status */ +/* if (s->highspeed) */ +/* break; */ + + if (0 == s->needed_bytes) { + command (s, val); +#if 0 + if (0 == s->needed_bytes) { + log_dsp (s); + } +#endif + } + else { + if (s->in_index == sizeof (s->in2_data)) { + dolog ("in data overrun\n"); + } + else { + s->in2_data[s->in_index++] = val; + if (s->in_index == s->needed_bytes) { + s->needed_bytes = 0; + complete (s); +#if 0 + log_dsp (s); +#endif + } + } + } + break; + + default: + ldebug ("(nport=%#x, val=%#x)\n", nport, val); + break; + } +} + +static IO_READ_PROTO (dsp_read) +{ + SB16State *s = opaque; + int iport, retval, ack = 0; + + iport = nport - s->port; + + switch (iport) { + case 0x06: /* reset */ + retval = 0xff; + break; + + case 0x0a: /* read data */ + if (s->out_data_len) { + retval = s->out_data[--s->out_data_len]; + s->last_read_byte = retval; + } + else { + dolog ("empty output buffer\n"); + retval = s->last_read_byte; + /* goto error; */ + } + break; + + case 0x0c: /* 0 can write */ + retval = s->can_write ? 0 : 0x80; + break; + + case 0x0d: /* timer interrupt clear */ + /* dolog ("timer interrupt clear\n"); */ + retval = 0; + break; + + case 0x0e: /* data available status | irq 8 ack */ + retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80; + if (s->mixer_regs[0x82] & 1) { + ack = 1; + s->mixer_regs[0x82] &= 1; + pic_set_irq (s->irq, 0); + } + break; + + case 0x0f: /* irq 16 ack */ + retval = 0xff; + if (s->mixer_regs[0x82] & 2) { + ack = 1; + s->mixer_regs[0x82] &= 2; + pic_set_irq (s->irq, 0); + } + break; + + default: + goto error; + } + + if (!ack) + ldebug ("read %#x -> %#x\n", nport, retval); + + return retval; + + error: + dolog ("WARNING dsp_read %#x error\n", nport); + return 0xff; +} + +static void reset_mixer (SB16State *s) +{ + int i; + + memset (s->mixer_regs, 0xff, 0x7f); + memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83); + + s->mixer_regs[0x02] = 4; /* master volume 3bits */ + s->mixer_regs[0x06] = 4; /* MIDI volume 3bits */ + s->mixer_regs[0x08] = 0; /* CD volume 3bits */ + s->mixer_regs[0x0a] = 0; /* voice volume 2bits */ + + /* d5=input filt, d3=lowpass filt, d1,d2=input source */ + s->mixer_regs[0x0c] = 0; + + /* d5=output filt, d1=stereo switch */ + s->mixer_regs[0x0e] = 0; + + /* voice volume L d5,d7, R d1,d3 */ + s->mixer_regs[0x04] = (4 << 5) | (4 << 1); + /* master ... */ + s->mixer_regs[0x22] = (4 << 5) | (4 << 1); + /* MIDI ... */ + s->mixer_regs[0x26] = (4 << 5) | (4 << 1); + + for (i = 0x30; i < 0x48; i++) { + s->mixer_regs[i] = 0x20; + } +} + +static IO_WRITE_PROTO(mixer_write_indexb) +{ + SB16State *s = opaque; + s->mixer_nreg = val; +} + +static IO_WRITE_PROTO(mixer_write_datab) +{ + SB16State *s = opaque; + + ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val); + if (s->mixer_nreg > sizeof (s->mixer_regs)) + return; + + switch (s->mixer_nreg) { + case 0x00: + reset_mixer (s); + break; + + case 0x80: + { + int irq = irq_of_magic (val); + ldebug ("setting irq to %d (val=%#x)\n", irq, val); + if (irq > 0) + s->irq = irq; + } + break; + + case 0x81: + { + int dma, hdma; + + dma = lsbindex (val & 0xf); + hdma = lsbindex (val & 0xf0); + dolog ("attempt to set DMA register 8bit %d, 16bit %d (val=%#x)\n", + dma, hdma, val); +#if 0 + s->dma = dma; + s->hdma = hdma; +#endif + } + break; + + case 0x82: + dolog ("attempt to write into IRQ status register (val=%#x)\n", + val); + return; + + default: + if (s->mixer_nreg >= 0x80) + dolog ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val); + break; + } + + s->mixer_regs[s->mixer_nreg] = val; +} + +static IO_WRITE_PROTO(mixer_write_indexw) +{ + mixer_write_indexb (opaque, nport, val & 0xff); + mixer_write_datab (opaque, nport, (val >> 8) & 0xff); +} + +static IO_READ_PROTO(mixer_read) +{ + SB16State *s = opaque; +#ifndef DEBUG_SB16_MOST + if (s->mixer_nreg != 0x82) +#endif + ldebug ("mixer_read[%#x] -> %#x\n", + s->mixer_nreg, s->mixer_regs[s->mixer_nreg]); + return s->mixer_regs[s->mixer_nreg]; +} + +static int write_audio (SB16State *s, int nchan, int dma_pos, + int dma_len, int len) +{ + int temp, net; + uint8_t tmpbuf[4096]; + + temp = len; + net = 0; + + while (temp) { + int left = dma_len - dma_pos; + int to_copy, copied; + + to_copy = audio_MIN (temp, left); + if (to_copy > sizeof(tmpbuf)) + to_copy = sizeof(tmpbuf); + + copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy); + copied = AUD_write (s->voice, tmpbuf, copied); + + temp -= copied; + dma_pos = (dma_pos + copied) % dma_len; + net += copied; + + if (!copied) + break; + } + + return net; +} + +static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len) +{ + SB16State *s = opaque; + int free, rfree, till, copy, written, elapsed; + + if (s->left_till_irq < 0) { + s->left_till_irq = s->block_size; + } + + elapsed = AUD_calc_elapsed (s->voice); + free = elapsed;/* AUD_get_free (s->voice); */ + rfree = free; + free = audio_MIN (free, elapsed) & ~s->align; + + if ((free <= 0) || !dma_len) { + return dma_pos; + } + + copy = free; + till = s->left_till_irq; + +#ifdef DEBUG_SB16_MOST + dolog ("pos:%06d free:%d,%d till:%d len:%d\n", + dma_pos, free, AUD_get_free (s->voice), till, dma_len); +#endif + + if (till <= copy) { + if (0 == s->dma_auto) { + copy = till; + } + } + + written = write_audio (s, nchan, dma_pos, dma_len, copy); + dma_pos = (dma_pos + written) % dma_len; + s->left_till_irq -= written; + + if (s->left_till_irq <= 0) { + s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1; + pic_set_irq (s->irq, 1); + if (0 == s->dma_auto) { + control (s, 0); + speaker (s, 0); + } + } + +#ifdef DEBUG_SB16_MOST + ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n", + dma_pos, free, dma_len, s->left_till_irq, copy, written, + s->block_size); +#endif + + while (s->left_till_irq <= 0) { + s->left_till_irq = s->block_size + s->left_till_irq; + } + + AUD_adjust (s->voice, written); + return dma_pos; +} + +void SB_timer (void *opaque) +{ + SB16State *s = opaque; + AUD_run (); + qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1); +} + +static void SB_save (QEMUFile *f, void *opaque) +{ + SB16State *s = opaque; + + qemu_put_be32s (f, &s->irq); + qemu_put_be32s (f, &s->dma); + qemu_put_be32s (f, &s->hdma); + qemu_put_be32s (f, &s->port); + qemu_put_be32s (f, &s->ver); + qemu_put_be32s (f, &s->in_index); + qemu_put_be32s (f, &s->out_data_len); + qemu_put_be32s (f, &s->fmt_stereo); + qemu_put_be32s (f, &s->fmt_signed); + qemu_put_be32s (f, &s->fmt_bits); + qemu_put_be32s (f, &s->fmt); + qemu_put_be32s (f, &s->dma_auto); + qemu_put_be32s (f, &s->block_size); + qemu_put_be32s (f, &s->fifo); + qemu_put_be32s (f, &s->freq); + qemu_put_be32s (f, &s->time_const); + qemu_put_be32s (f, &s->speaker); + qemu_put_be32s (f, &s->needed_bytes); + qemu_put_be32s (f, &s->cmd); + qemu_put_be32s (f, &s->use_hdma); + qemu_put_be32s (f, &s->highspeed); + qemu_put_be32s (f, &s->can_write); + qemu_put_be32s (f, &s->v2x6); + + qemu_put_8s (f, &s->csp_param); + qemu_put_8s (f, &s->csp_value); + qemu_put_8s (f, &s->csp_mode); + qemu_put_8s (f, &s->csp_param); + qemu_put_buffer (f, s->csp_regs, 256); + qemu_put_8s (f, &s->csp_index); + qemu_put_buffer (f, s->csp_reg83, 4); + qemu_put_be32s (f, &s->csp_reg83r); + qemu_put_be32s (f, &s->csp_reg83w); + + qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data)); + qemu_put_buffer (f, s->out_data, sizeof (s->out_data)); + qemu_put_8s (f, &s->test_reg); + qemu_put_8s (f, &s->last_read_byte); + + qemu_put_be32s (f, &s->nzero); + qemu_put_be32s (f, &s->left_till_irq); + qemu_put_be32s (f, &s->dma_running); + qemu_put_be32s (f, &s->bytes_per_second); + qemu_put_be32s (f, &s->align); + + qemu_put_be32s (f, &s->mixer_nreg); + qemu_put_buffer (f, s->mixer_regs, 256); +} + +static int SB_load (QEMUFile *f, void *opaque, int version_id) +{ + SB16State *s = opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_be32s (f, &s->irq); + qemu_get_be32s (f, &s->dma); + qemu_get_be32s (f, &s->hdma); + qemu_get_be32s (f, &s->port); + qemu_get_be32s (f, &s->ver); + qemu_get_be32s (f, &s->in_index); + qemu_get_be32s (f, &s->out_data_len); + qemu_get_be32s (f, &s->fmt_stereo); + qemu_get_be32s (f, &s->fmt_signed); + qemu_get_be32s (f, &s->fmt_bits); + qemu_get_be32s (f, &s->fmt); + qemu_get_be32s (f, &s->dma_auto); + qemu_get_be32s (f, &s->block_size); + qemu_get_be32s (f, &s->fifo); + qemu_get_be32s (f, &s->freq); + qemu_get_be32s (f, &s->time_const); + qemu_get_be32s (f, &s->speaker); + qemu_get_be32s (f, &s->needed_bytes); + qemu_get_be32s (f, &s->cmd); + qemu_get_be32s (f, &s->use_hdma); + qemu_get_be32s (f, &s->highspeed); + qemu_get_be32s (f, &s->can_write); + qemu_get_be32s (f, &s->v2x6); + + qemu_get_8s (f, &s->csp_param); + qemu_get_8s (f, &s->csp_value); + qemu_get_8s (f, &s->csp_mode); + qemu_get_8s (f, &s->csp_param); + qemu_get_buffer (f, s->csp_regs, 256); + qemu_get_8s (f, &s->csp_index); + qemu_get_buffer (f, s->csp_reg83, 4); + qemu_get_be32s (f, &s->csp_reg83r); + qemu_get_be32s (f, &s->csp_reg83w); + + qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data)); + qemu_get_buffer (f, s->out_data, sizeof (s->out_data)); + qemu_get_8s (f, &s->test_reg); + qemu_get_8s (f, &s->last_read_byte); + + qemu_get_be32s (f, &s->nzero); + qemu_get_be32s (f, &s->left_till_irq); + qemu_get_be32s (f, &s->dma_running); + qemu_get_be32s (f, &s->bytes_per_second); + qemu_get_be32s (f, &s->align); + + qemu_get_be32s (f, &s->mixer_nreg); + qemu_get_buffer (f, s->mixer_regs, 256); + + if (s->voice) { + AUD_close (s->voice); + s->voice = NULL; + } + + if (s->dma_running) { + if (s->freq) + s->voice = AUD_open (s->voice, "sb16", s->freq, + 1 << s->fmt_stereo, s->fmt); + + control (s, 1); + speaker (s, s->speaker); + } + return 0; +} + +void SB16_init (void) +{ + SB16State *s = &dsp; + int i; + static const uint8_t dsp_write_ports[] = {0x6, 0xc}; + static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf}; + + s->ts = qemu_new_timer (vm_clock, SB_timer, s); + if (!s->ts) + return; + + s->irq = conf.irq; + s->dma = conf.dma; + s->hdma = conf.hdma; + s->port = conf.port; + s->ver = conf.ver_lo | (conf.ver_hi << 8); + + s->mixer_regs[0x80] = magic_of_irq (s->irq); + s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma); + s->mixer_regs[0x82] = 2 << 5; + + s->csp_regs[5] = 1; + s->csp_regs[9] = 0xf8; + + reset_mixer (s); + s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s); + if (!s->aux_ts) + return; + + for (i = 0; i < LENOFA (dsp_write_ports); i++) { + register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s); + } + + for (i = 0; i < LENOFA (dsp_read_ports); i++) { + register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s); + } + + register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s); + register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s); + register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s); + register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s); + + DMA_register_channel (s->hdma, SB_read_DMA, s); + DMA_register_channel (s->dma, SB_read_DMA, s); + s->can_write = 1; + + qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1); + register_savevm ("sb16", 0, 1, SB_save, SB_load, s); +} diff --git a/tools/ioemu/hw/sched.c b/tools/ioemu/hw/sched.c new file mode 100644 index 0000000000..2ab966de4c --- /dev/null +++ b/tools/ioemu/hw/sched.c @@ -0,0 +1,268 @@ +/* + * QEMU interrupt controller emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" +//#define DEBUG_IRQ_COUNT + +/* These registers are used for sending/receiving irqs from/to + * different cpu's. + */ +struct sun4m_intreg_percpu { + unsigned int tbt; /* Intrs pending for this cpu, by PIL. */ + /* These next two registers are WRITE-ONLY and are only + * "on bit" sensitive, "off bits" written have NO affect. + */ + unsigned int clear; /* Clear this cpus irqs here. */ + unsigned int set; /* Set this cpus irqs here. */ +}; +/* + * djhr + * Actually the clear and set fields in this struct are misleading.. + * according to the SLAVIO manual (and the same applies for the SEC) + * the clear field clears bits in the mask which will ENABLE that IRQ + * the set field sets bits in the mask to DISABLE the IRQ. + * + * Also the undirected_xx address in the SLAVIO is defined as + * RESERVED and write only.. + * + * DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor + * sun4m machines, for MP the layout makes more sense. + */ +struct sun4m_intreg_master { + unsigned int tbt; /* IRQ's that are pending, see sun4m masks. */ + unsigned int irqs; /* Master IRQ bits. */ + + /* Again, like the above, two these registers are WRITE-ONLY. */ + unsigned int clear; /* Clear master IRQ's by setting bits here. */ + unsigned int set; /* Set master IRQ's by setting bits here. */ + + /* This register is both READ and WRITE. */ + unsigned int undirected_target; /* Which cpu gets undirected irqs. */ +}; + +#define SUN4M_INT_ENABLE 0x80000000 +#define SUN4M_INT_E14 0x00000080 +#define SUN4M_INT_E10 0x00080000 + +#define SUN4M_HARD_INT(x) (0x000000001 << (x)) +#define SUN4M_SOFT_INT(x) (0x000010000 << (x)) + +#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ +#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ +#define SUN4M_INT_M2S_WRITE 0x20000000 /* write buffer error */ +#define SUN4M_INT_ECC 0x10000000 /* ecc memory error */ +#define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */ +#define SUN4M_INT_MODULE 0x00200000 /* module interrupt */ +#define SUN4M_INT_VIDEO 0x00100000 /* onboard video */ +#define SUN4M_INT_REALTIME 0x00080000 /* system timer */ +#define SUN4M_INT_SCSI 0x00040000 /* onboard scsi */ +#define SUN4M_INT_AUDIO 0x00020000 /* audio/isdn */ +#define SUN4M_INT_ETHERNET 0x00010000 /* onboard ethernet */ +#define SUN4M_INT_SERIAL 0x00008000 /* serial ports */ +#define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */ + +#define SUN4M_INT_SBUS(x) (1 << (x+7)) +#define SUN4M_INT_VME(x) (1 << (x)) + +typedef struct SCHEDState { + uint32_t addr, addrg; + uint32_t intreg_pending; + uint32_t intreg_enabled; + uint32_t intregm_pending; + uint32_t intregm_enabled; +} SCHEDState; + +static SCHEDState *ps; + +#ifdef DEBUG_IRQ_COUNT +static uint64_t irq_count[32]; +#endif + +static uint32_t intreg_mem_readl(void *opaque, target_phys_addr_t addr) +{ + SCHEDState *s = opaque; + uint32_t saddr; + + saddr = (addr - s->addr) >> 2; + switch (saddr) { + case 0: + return s->intreg_pending; + break; + default: + break; + } + return 0; +} + +static void intreg_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + SCHEDState *s = opaque; + uint32_t saddr; + + saddr = (addr - s->addr) >> 2; + switch (saddr) { + case 0: + s->intreg_pending = val; + break; + case 1: // clear + s->intreg_enabled &= ~val; + break; + case 2: // set + s->intreg_enabled |= val; + break; + default: + break; + } +} + +static CPUReadMemoryFunc *intreg_mem_read[3] = { + intreg_mem_readl, + intreg_mem_readl, + intreg_mem_readl, +}; + +static CPUWriteMemoryFunc *intreg_mem_write[3] = { + intreg_mem_writel, + intreg_mem_writel, + intreg_mem_writel, +}; + +static uint32_t intregm_mem_readl(void *opaque, target_phys_addr_t addr) +{ + SCHEDState *s = opaque; + uint32_t saddr; + + saddr = (addr - s->addrg) >> 2; + switch (saddr) { + case 0: + return s->intregm_pending; + break; + case 1: + return s->intregm_enabled; + break; + default: + break; + } + return 0; +} + +static void intregm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + SCHEDState *s = opaque; + uint32_t saddr; + + saddr = (addr - s->addrg) >> 2; + switch (saddr) { + case 0: + s->intregm_pending = val; + break; + case 1: + s->intregm_enabled = val; + break; + case 2: // clear + s->intregm_enabled &= ~val; + break; + case 3: // set + s->intregm_enabled |= val; + break; + default: + break; + } +} + +static CPUReadMemoryFunc *intregm_mem_read[3] = { + intregm_mem_readl, + intregm_mem_readl, + intregm_mem_readl, +}; + +static CPUWriteMemoryFunc *intregm_mem_write[3] = { + intregm_mem_writel, + intregm_mem_writel, + intregm_mem_writel, +}; + +void pic_info(void) +{ + term_printf("per-cpu: pending 0x%08x, enabled 0x%08x\n", ps->intreg_pending, ps->intreg_enabled); + term_printf("master: pending 0x%08x, enabled 0x%08x\n", ps->intregm_pending, ps->intregm_enabled); +} + +void irq_info(void) +{ +#ifndef DEBUG_IRQ_COUNT + term_printf("irq statistic code not compiled.\n"); +#else + int i; + int64_t count; + + term_printf("IRQ statistics:\n"); + for (i = 0; i < 32; i++) { + count = irq_count[i]; + if (count > 0) + term_printf("%2d: %lld\n", i, count); + } +#endif +} + +static const unsigned int intr_to_mask[16] = { + 0, 0, 0, 0, 0, 0, SUN4M_INT_ETHERNET, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}; + +void pic_set_irq(int irq, int level) +{ + if (irq < 16) { + unsigned int mask = intr_to_mask[irq]; + ps->intreg_pending |= 1 << irq; + if (ps->intregm_enabled & mask) { + cpu_single_env->interrupt_index = irq; + cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD); + } + } +#ifdef DEBUG_IRQ_COUNT + if (level == 1) + irq_count[irq]++; +#endif +} + +void sched_init(uint32_t addr, uint32_t addrg) +{ + int intreg_io_memory, intregm_io_memory; + SCHEDState *s; + + s = qemu_mallocz(sizeof(SCHEDState)); + if (!s) + return; + s->addr = addr; + s->addrg = addrg; + + intreg_io_memory = cpu_register_io_memory(0, intreg_mem_read, intreg_mem_write, s); + cpu_register_physical_memory(addr, 3, intreg_io_memory); + + intregm_io_memory = cpu_register_io_memory(0, intregm_mem_read, intregm_mem_write, s); + cpu_register_physical_memory(addrg, 5, intregm_io_memory); + + ps = s; +} + diff --git a/tools/ioemu/hw/serial.c b/tools/ioemu/hw/serial.c new file mode 100644 index 0000000000..3fe482c391 --- /dev/null +++ b/tools/ioemu/hw/serial.c @@ -0,0 +1,279 @@ +/* + * QEMU 16450 UART emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +//#define DEBUG_SERIAL + +#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */ + +#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */ +#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */ +#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */ +#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */ + +#define UART_IIR_NO_INT 0x01 /* No interrupts pending */ +#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */ + +#define UART_IIR_MSI 0x00 /* Modem status interrupt */ +#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ +#define UART_IIR_RDI 0x04 /* Receiver data interrupt */ +#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ + +/* + * These are the definitions for the Modem Control Register + */ +#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ +#define UART_MCR_OUT2 0x08 /* Out2 complement */ +#define UART_MCR_OUT1 0x04 /* Out1 complement */ +#define UART_MCR_RTS 0x02 /* RTS complement */ +#define UART_MCR_DTR 0x01 /* DTR complement */ + +/* + * These are the definitions for the Modem Status Register + */ +#define UART_MSR_DCD 0x80 /* Data Carrier Detect */ +#define UART_MSR_RI 0x40 /* Ring Indicator */ +#define UART_MSR_DSR 0x20 /* Data Set Ready */ +#define UART_MSR_CTS 0x10 /* Clear to Send */ +#define UART_MSR_DDCD 0x08 /* Delta DCD */ +#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */ +#define UART_MSR_DDSR 0x02 /* Delta DSR */ +#define UART_MSR_DCTS 0x01 /* Delta CTS */ +#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */ + +#define UART_LSR_TEMT 0x40 /* Transmitter empty */ +#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ +#define UART_LSR_BI 0x10 /* Break interrupt indicator */ +#define UART_LSR_FE 0x08 /* Frame error indicator */ +#define UART_LSR_PE 0x04 /* Parity error indicator */ +#define UART_LSR_OE 0x02 /* Overrun error indicator */ +#define UART_LSR_DR 0x01 /* Receiver data ready */ + +struct SerialState { + uint8_t divider; + uint8_t rbr; /* receive register */ + uint8_t ier; + uint8_t iir; /* read only */ + uint8_t lcr; + uint8_t mcr; + uint8_t lsr; /* read only */ + uint8_t msr; + uint8_t scr; + /* NOTE: this hidden state is necessary for tx irq generation as + it can be reset while reading iir */ + int thr_ipending; + int irq; + CharDriverState *chr; +}; + +static void serial_update_irq(SerialState *s) +{ + if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) { + s->iir = UART_IIR_RDI; + } else if (s->thr_ipending && (s->ier & UART_IER_THRI)) { + s->iir = UART_IIR_THRI; + } else { + s->iir = UART_IIR_NO_INT; + } + if (s->iir != UART_IIR_NO_INT) { + pic_set_irq(s->irq, 1); + } else { + pic_set_irq(s->irq, 0); + } +} + +static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ + SerialState *s = opaque; + unsigned char ch; + + addr &= 7; +#ifdef DEBUG_SERIAL + printf("serial: write addr=0x%02x val=0x%02x\n", addr, val); +#endif + switch(addr) { + default: + case 0: + if (s->lcr & UART_LCR_DLAB) { + s->divider = (s->divider & 0xff00) | val; + } else { + s->thr_ipending = 0; + s->lsr &= ~UART_LSR_THRE; + serial_update_irq(s); + ch = val; + qemu_chr_write(s->chr, &ch, 1); + s->thr_ipending = 1; + s->lsr |= UART_LSR_THRE; + s->lsr |= UART_LSR_TEMT; + serial_update_irq(s); + } + break; + case 1: + if (s->lcr & UART_LCR_DLAB) { + s->divider = (s->divider & 0x00ff) | (val << 8); + } else { + s->ier = val & 0x0f; + if (s->lsr & UART_LSR_THRE) { + s->thr_ipending = 1; + } + serial_update_irq(s); + } + break; + case 2: + break; + case 3: + s->lcr = val; + break; + case 4: + s->mcr = val & 0x1f; + break; + case 5: + break; + case 6: + s->msr = val; + break; + case 7: + s->scr = val; + break; + } +} + +static uint32_t serial_ioport_read(void *opaque, uint32_t addr) +{ + SerialState *s = opaque; + uint32_t ret; + + addr &= 7; + switch(addr) { + default: + case 0: + if (s->lcr & UART_LCR_DLAB) { + ret = s->divider & 0xff; + } else { + ret = s->rbr; + s->lsr &= ~(UART_LSR_DR | UART_LSR_BI); + serial_update_irq(s); + } + break; + case 1: + if (s->lcr & UART_LCR_DLAB) { + ret = (s->divider >> 8) & 0xff; + } else { + ret = s->ier; + } + break; + case 2: + ret = s->iir; + /* reset THR pending bit */ + if ((ret & 0x7) == UART_IIR_THRI) + s->thr_ipending = 0; + serial_update_irq(s); + break; + case 3: + ret = s->lcr; + break; + case 4: + ret = s->mcr; + break; + case 5: + ret = s->lsr; + break; + case 6: + if (s->mcr & UART_MCR_LOOP) { + /* in loopback, the modem output pins are connected to the + inputs */ + ret = (s->mcr & 0x0c) << 4; + ret |= (s->mcr & 0x02) << 3; + ret |= (s->mcr & 0x01) << 5; + } else { + ret = s->msr; + } + break; + case 7: + ret = s->scr; + break; + } +#ifdef DEBUG_SERIAL + printf("serial: read addr=0x%02x val=0x%02x\n", addr, ret); +#endif + return ret; +} + +static int serial_can_receive(SerialState *s) +{ + return !(s->lsr & UART_LSR_DR); +} + +static void serial_receive_byte(SerialState *s, int ch) +{ + s->rbr = ch; + s->lsr |= UART_LSR_DR; + serial_update_irq(s); +} + +static void serial_receive_break(SerialState *s) +{ + s->rbr = 0; + s->lsr |= UART_LSR_BI | UART_LSR_DR; + serial_update_irq(s); +} + +static int serial_can_receive1(void *opaque) +{ + SerialState *s = opaque; + return serial_can_receive(s); +} + +static void serial_receive1(void *opaque, const uint8_t *buf, int size) +{ + SerialState *s = opaque; + serial_receive_byte(s, buf[0]); +} + +static void serial_event(void *opaque, int event) +{ + SerialState *s = opaque; + if (event == CHR_EVENT_BREAK) + serial_receive_break(s); +} + +/* If fd is zero, it means that the serial device uses the console */ +SerialState *serial_init(int base, int irq, CharDriverState *chr) +{ + SerialState *s; + + s = qemu_mallocz(sizeof(SerialState)); + if (!s) + return NULL; + s->irq = irq; + s->lsr = UART_LSR_TEMT | UART_LSR_THRE; + s->iir = UART_IIR_NO_INT; + + register_ioport_write(base, 8, 1, serial_ioport_write, s); + register_ioport_read(base, 8, 1, serial_ioport_read, s); + s->chr = chr; + qemu_chr_add_read_handler(chr, serial_can_receive1, serial_receive1, s); + qemu_chr_add_event_handler(chr, serial_event); + return s; +} diff --git a/tools/ioemu/hw/sun4m.c b/tools/ioemu/hw/sun4m.c new file mode 100644 index 0000000000..80305e09c3 --- /dev/null +++ b/tools/ioemu/hw/sun4m.c @@ -0,0 +1,113 @@ +/* + * QEMU Sun4m System Emulator + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" +#include "m48t08.h" + +#define KERNEL_LOAD_ADDR 0x00004000 +#define MMU_CONTEXT_TBL 0x00003000 +#define MMU_L1PTP (MMU_CONTEXT_TBL + 0x0400) +#define MMU_L2PTP (MMU_CONTEXT_TBL + 0x0800) +#define PROM_ADDR 0xffd04000 +#define PROM_FILENAMEB "proll.bin" +#define PROM_FILENAMEE "proll.elf" +#define PROLL_MAGIC_ADDR 0x20000000 +#define PHYS_JJ_EEPROM 0x71200000 /* [2000] MK48T08 */ +#define PHYS_JJ_IDPROM_OFF 0x1FD8 +#define PHYS_JJ_EEPROM_SIZE 0x2000 +#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */ +#define PHYS_JJ_TCX_FB 0x50800000 /* Start address, frame buffer body */ +#define PHYS_JJ_TCX_0E 0x5E000000 /* Top address, one byte used. */ +#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */ +#define PHYS_JJ_LEDMA 0x78400010 /* ledma, off by 10 from unused SCSI */ +#define PHYS_JJ_LE 0x78C00000 /* LANCE, typical sun4m */ +#define PHYS_JJ_LE_IRQ 6 +#define PHYS_JJ_CLOCK 0x71D00000 +#define PHYS_JJ_CLOCK_IRQ 10 +#define PHYS_JJ_CLOCK1 0x71D10000 +#define PHYS_JJ_CLOCK1_IRQ 14 +#define PHYS_JJ_INTR0 0x71E00000 /* CPU0 interrupt control registers */ +#define PHYS_JJ_INTR_G 0x71E10000 /* Master interrupt control registers */ + +/* TSC handling */ + +uint64_t cpu_get_tsc() +{ + return qemu_get_clock(vm_clock); +} + +void DMA_run() {} +void SB16_run() {} +int serial_can_receive(SerialState *s) { return 0; } +void serial_receive_byte(SerialState *s, int ch) {} +void serial_receive_break(SerialState *s) {} + +static m48t08_t *nvram; + +/* Sun4m hardware initialisation */ +void sun4m_init(int ram_size, int vga_ram_size, int boot_device, + DisplayState *ds, const char **fd_filename, int snapshot, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename) +{ + char buf[1024]; + int ret, linux_boot; + unsigned long bios_offset; + + linux_boot = (kernel_filename != NULL); + + /* allocate RAM */ + cpu_register_physical_memory(0, ram_size, 0); + bios_offset = ram_size; + + iommu_init(PHYS_JJ_IOMMU); + sched_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G); + tcx_init(ds, PHYS_JJ_TCX_FB); + lance_init(&nd_table[0], PHYS_JJ_LE_IRQ, PHYS_JJ_LE, PHYS_JJ_LEDMA); + nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE, &nd_table[0].macaddr); + timer_init(PHYS_JJ_CLOCK, PHYS_JJ_CLOCK_IRQ); + timer_init(PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ); + magic_init(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR, PROLL_MAGIC_ADDR); + + /* We load Proll as the kernel and start it. It will issue a magic + IO to load the real kernel */ + if (linux_boot) { + snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB); + ret = load_kernel(buf, + phys_ram_base + KERNEL_LOAD_ADDR); + if (ret < 0) { + fprintf(stderr, "qemu: could not load kernel '%s'\n", + buf); + exit(1); + } + } + /* Setup a MMU entry for entire address space */ + stl_raw(phys_ram_base + MMU_CONTEXT_TBL, (MMU_L1PTP >> 4) | 1); + stl_raw(phys_ram_base + MMU_L1PTP, (MMU_L2PTP >> 4) | 1); + stl_raw(phys_ram_base + MMU_L1PTP + (0x01 << 2), (MMU_L2PTP >> 4) | 1); // 01.. == 00.. + stl_raw(phys_ram_base + MMU_L1PTP + (0xff << 2), (MMU_L2PTP >> 4) | 1); // ff.. == 00.. + stl_raw(phys_ram_base + MMU_L1PTP + (0xf0 << 2), (MMU_L2PTP >> 4) | 1); // f0.. == 00.. + /* 3 = U:RWX S:RWX */ + stl_raw(phys_ram_base + MMU_L2PTP, (3 << PTE_ACCESS_SHIFT) | 2); + stl_raw(phys_ram_base + MMU_L2PTP, ((0x01 << PTE_PPN_SHIFT) >> 4 ) | (3 << PTE_ACCESS_SHIFT) | 2); +} diff --git a/tools/ioemu/hw/tcx.c b/tools/ioemu/hw/tcx.c new file mode 100644 index 0000000000..7f979946fc --- /dev/null +++ b/tools/ioemu/hw/tcx.c @@ -0,0 +1,207 @@ +/* + * QEMU Sun4m System Emulator + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +#define MAXX 1024 +#define MAXY 768 +#define XSZ (8*80) +#define YSZ (24*11) +#define XOFF (MAXX-XSZ) +#define YOFF (MAXY-YSZ) + +typedef struct TCXState { + uint32_t addr; + DisplayState *ds; + uint8_t *vram; +} TCXState; + +static TCXState *ts; + +void vga_update_display() +{ + dpy_update(ts->ds, 0, 0, XSZ, YSZ); +} + +void vga_invalidate_display() {} + +static uint32_t tcx_mem_readb(void *opaque, target_phys_addr_t addr) +{ + TCXState *s = opaque; + uint32_t saddr; + unsigned int x, y; + + saddr = addr - s->addr - YOFF*MAXX - XOFF; + y = saddr / MAXX; + x = saddr - y * MAXX; + if (x < XSZ && y < YSZ) { + return s->vram[y * XSZ + x]; + } + return 0; +} + +static uint32_t tcx_mem_readw(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; +#ifdef TARGET_WORDS_BIGENDIAN + v = tcx_mem_readb(opaque, addr) << 8; + v |= tcx_mem_readb(opaque, addr + 1); +#else + v = tcx_mem_readb(opaque, addr); + v |= tcx_mem_readb(opaque, addr + 1) << 8; +#endif + return v; +} + +static uint32_t tcx_mem_readl(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; +#ifdef TARGET_WORDS_BIGENDIAN + v = tcx_mem_readb(opaque, addr) << 24; + v |= tcx_mem_readb(opaque, addr + 1) << 16; + v |= tcx_mem_readb(opaque, addr + 2) << 8; + v |= tcx_mem_readb(opaque, addr + 3); +#else + v = tcx_mem_readb(opaque, addr); + v |= tcx_mem_readb(opaque, addr + 1) << 8; + v |= tcx_mem_readb(opaque, addr + 2) << 16; + v |= tcx_mem_readb(opaque, addr + 3) << 24; +#endif + return v; +} + +static void tcx_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + TCXState *s = opaque; + uint32_t saddr; + unsigned int x, y; + char *sptr; + + saddr = addr - s->addr - YOFF*MAXX - XOFF; + y = saddr / MAXX; + x = saddr - y * MAXX; + if (x < XSZ && y < YSZ) { + sptr = s->ds->data; + if (sptr) { + if (s->ds->depth == 24 || s->ds->depth == 32) { + /* XXX need to do CLUT translation */ + sptr[y * s->ds->linesize + x*4] = val & 0xff; + sptr[y * s->ds->linesize + x*4+1] = val & 0xff; + sptr[y * s->ds->linesize + x*4+2] = val & 0xff; + } + else if (s->ds->depth == 8) { + sptr[y * s->ds->linesize + x] = val & 0xff; + } + } + cpu_physical_memory_set_dirty(addr); + s->vram[y * XSZ + x] = val & 0xff; + } +} + +static void tcx_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + tcx_mem_writeb(opaque, addr, (val >> 8) & 0xff); + tcx_mem_writeb(opaque, addr + 1, val & 0xff); +#else + tcx_mem_writeb(opaque, addr, val & 0xff); + tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff); +#endif +} + +static void tcx_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + tcx_mem_writeb(opaque, addr, (val >> 24) & 0xff); + tcx_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff); + tcx_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff); + tcx_mem_writeb(opaque, addr + 3, val & 0xff); +#else + tcx_mem_writeb(opaque, addr, val & 0xff); + tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff); + tcx_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff); + tcx_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff); +#endif +} + +static CPUReadMemoryFunc *tcx_mem_read[3] = { + tcx_mem_readb, + tcx_mem_readw, + tcx_mem_readl, +}; + +static CPUWriteMemoryFunc *tcx_mem_write[3] = { + tcx_mem_writeb, + tcx_mem_writew, + tcx_mem_writel, +}; + +void tcx_init(DisplayState *ds, uint32_t addr) +{ + TCXState *s; + int tcx_io_memory; + + s = qemu_mallocz(sizeof(TCXState)); + if (!s) + return; + s->ds = ds; + s->addr = addr; + ts = s; + tcx_io_memory = cpu_register_io_memory(0, tcx_mem_read, tcx_mem_write, s); + cpu_register_physical_memory(addr, 0x100000, + tcx_io_memory); + s->vram = qemu_mallocz(XSZ*YSZ); + dpy_resize(s->ds, XSZ, YSZ); +} + +void vga_screen_dump(const char *filename) +{ + TCXState *s = ts; + FILE *f; + uint8_t *d, *d1; + unsigned int v; + int y, x; + + f = fopen(filename, "wb"); + if (!f) + return -1; + fprintf(f, "P6\n%d %d\n%d\n", + XSZ, YSZ, 255); + d1 = s->vram; + for(y = 0; y < YSZ; y++) { + d = d1; + for(x = 0; x < XSZ; x++) { + v = *d; + fputc((v) & 0xff, f); + fputc((v) & 0xff, f); + fputc((v) & 0xff, f); + d++; + } + d1 += XSZ; + } + fclose(f); + return; +} + + + diff --git a/tools/ioemu/hw/timer.c b/tools/ioemu/hw/timer.c new file mode 100644 index 0000000000..e393fa36fd --- /dev/null +++ b/tools/ioemu/hw/timer.c @@ -0,0 +1,97 @@ +/* + * QEMU Sparc timer controller emulation + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +/* + * Registers of hardware timer in sun4m. + */ +struct sun4m_timer_percpu { + volatile unsigned int l14_timer_limit; /* Initial value is 0x009c4000 */ + volatile unsigned int l14_cur_count; +}; + +struct sun4m_timer_global { + volatile unsigned int l10_timer_limit; + volatile unsigned int l10_cur_count; +}; + +typedef struct TIMERState { + uint32_t addr; + uint32_t timer_regs[2]; + int irq; +} TIMERState; + +static uint32_t timer_mem_readl(void *opaque, target_phys_addr_t addr) +{ + TIMERState *s = opaque; + uint32_t saddr; + + saddr = (addr - s->addr) >> 2; + switch (saddr) { + default: + return s->timer_regs[saddr]; + break; + } + return 0; +} + +static void timer_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + TIMERState *s = opaque; + uint32_t saddr; + + saddr = (addr - s->addr) >> 2; + switch (saddr) { + default: + s->timer_regs[saddr] = val; + break; + } +} + +static CPUReadMemoryFunc *timer_mem_read[3] = { + timer_mem_readl, + timer_mem_readl, + timer_mem_readl, +}; + +static CPUWriteMemoryFunc *timer_mem_write[3] = { + timer_mem_writel, + timer_mem_writel, + timer_mem_writel, +}; + +void timer_init(uint32_t addr, int irq) +{ + int timer_io_memory; + TIMERState *s; + + s = qemu_mallocz(sizeof(TIMERState)); + if (!s) + return; + s->addr = addr; + s->irq = irq; + + timer_io_memory = cpu_register_io_memory(0, timer_mem_read, timer_mem_write, s); + cpu_register_physical_memory(addr, 2, timer_io_memory); +} diff --git a/tools/ioemu/hw/vga.c b/tools/ioemu/hw/vga.c new file mode 100644 index 0000000000..d6358d92fe --- /dev/null +++ b/tools/ioemu/hw/vga.c @@ -0,0 +1,2059 @@ +/* + * QEMU VGA Emulator. + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" +#include "vga_int.h" + +//#define DEBUG_VGA +//#define DEBUG_VGA_MEM +//#define DEBUG_VGA_REG + +//#define DEBUG_S3 +//#define DEBUG_BOCHS_VBE + +/* S3 VGA is deprecated - another graphic card will be emulated */ +//#define CONFIG_S3VGA + +/* force some bits to zero */ +const uint8_t sr_mask[8] = { + (uint8_t)~0xfc, + (uint8_t)~0xc2, + (uint8_t)~0xf0, + (uint8_t)~0xc0, + (uint8_t)~0xf1, + (uint8_t)~0xff, + (uint8_t)~0xff, + (uint8_t)~0x00, +}; + +const uint8_t gr_mask[16] = { + (uint8_t)~0xf0, /* 0x00 */ + (uint8_t)~0xf0, /* 0x01 */ + (uint8_t)~0xf0, /* 0x02 */ + (uint8_t)~0xe0, /* 0x03 */ + (uint8_t)~0xfc, /* 0x04 */ + (uint8_t)~0x84, /* 0x05 */ + (uint8_t)~0xf0, /* 0x06 */ + (uint8_t)~0xf0, /* 0x07 */ + (uint8_t)~0x00, /* 0x08 */ + (uint8_t)~0xff, /* 0x09 */ + (uint8_t)~0xff, /* 0x0a */ + (uint8_t)~0xff, /* 0x0b */ + (uint8_t)~0xff, /* 0x0c */ + (uint8_t)~0xff, /* 0x0d */ + (uint8_t)~0xff, /* 0x0e */ + (uint8_t)~0xff, /* 0x0f */ +}; + +#define cbswap_32(__x) \ +((uint32_t)( \ + (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ + (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ + (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ + (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )) + +#ifdef WORDS_BIGENDIAN +#define PAT(x) cbswap_32(x) +#else +#define PAT(x) (x) +#endif + +#ifdef WORDS_BIGENDIAN +#define BIG 1 +#else +#define BIG 0 +#endif + +#ifdef WORDS_BIGENDIAN +#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff) +#else +#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff) +#endif + +static const uint32_t mask16[16] = { + PAT(0x00000000), + PAT(0x000000ff), + PAT(0x0000ff00), + PAT(0x0000ffff), + PAT(0x00ff0000), + PAT(0x00ff00ff), + PAT(0x00ffff00), + PAT(0x00ffffff), + PAT(0xff000000), + PAT(0xff0000ff), + PAT(0xff00ff00), + PAT(0xff00ffff), + PAT(0xffff0000), + PAT(0xffff00ff), + PAT(0xffffff00), + PAT(0xffffffff), +}; + +#undef PAT + +#ifdef WORDS_BIGENDIAN +#define PAT(x) (x) +#else +#define PAT(x) cbswap_32(x) +#endif + +static const uint32_t dmask16[16] = { + PAT(0x00000000), + PAT(0x000000ff), + PAT(0x0000ff00), + PAT(0x0000ffff), + PAT(0x00ff0000), + PAT(0x00ff00ff), + PAT(0x00ffff00), + PAT(0x00ffffff), + PAT(0xff000000), + PAT(0xff0000ff), + PAT(0xff00ff00), + PAT(0xff00ffff), + PAT(0xffff0000), + PAT(0xffff00ff), + PAT(0xffffff00), + PAT(0xffffffff), +}; + +static const uint32_t dmask4[4] = { + PAT(0x00000000), + PAT(0x0000ffff), + PAT(0xffff0000), + PAT(0xffffffff), +}; + +static uint32_t expand4[256]; +static uint16_t expand2[256]; +static uint8_t expand4to8[16]; + +VGAState *vga_state; +int vga_io_memory; + +static uint32_t vga_ioport_read(void *opaque, uint32_t addr) +{ + VGAState *s = opaque; + int val, index; + + /* check port range access depending on color/monochrome mode */ + if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) || + (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) { + val = 0xff; + } else { + switch(addr) { + case 0x3c0: + if (s->ar_flip_flop == 0) { + val = s->ar_index; + } else { + val = 0; + } + break; + case 0x3c1: + index = s->ar_index & 0x1f; + if (index < 21) + val = s->ar[index]; + else + val = 0; + break; + case 0x3c2: + val = s->st00; + break; + case 0x3c4: + val = s->sr_index; + break; + case 0x3c5: + val = s->sr[s->sr_index]; +#ifdef DEBUG_VGA_REG + printf("vga: read SR%x = 0x%02x\n", s->sr_index, val); +#endif + break; + case 0x3c7: + val = s->dac_state; + break; + case 0x3c8: + val = s->dac_write_index; + break; + case 0x3c9: + val = s->palette[s->dac_read_index * 3 + s->dac_sub_index]; + if (++s->dac_sub_index == 3) { + s->dac_sub_index = 0; + s->dac_read_index++; + } + break; + case 0x3ca: + val = s->fcr; + break; + case 0x3cc: + val = s->msr; + break; + case 0x3ce: + val = s->gr_index; + break; + case 0x3cf: + val = s->gr[s->gr_index]; +#ifdef DEBUG_VGA_REG + printf("vga: read GR%x = 0x%02x\n", s->gr_index, val); +#endif + break; + case 0x3b4: + case 0x3d4: + val = s->cr_index; + break; + case 0x3b5: + case 0x3d5: + val = s->cr[s->cr_index]; +#ifdef DEBUG_VGA_REG + printf("vga: read CR%x = 0x%02x\n", s->cr_index, val); +#endif +#ifdef DEBUG_S3 + if (s->cr_index >= 0x20) + printf("S3: CR read index=0x%x val=0x%x\n", + s->cr_index, val); +#endif + break; + case 0x3ba: + case 0x3da: + /* just toggle to fool polling */ + s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE; + val = s->st01; + s->ar_flip_flop = 0; + break; + default: + val = 0x00; + break; + } + } +#if defined(DEBUG_VGA) + printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val); +#endif + return val; +} + +static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val) +{ + VGAState *s = opaque; + int index; + + /* check port range access depending on color/monochrome mode */ + if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) || + (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) + return; + +#ifdef DEBUG_VGA + printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val); +#endif + + switch(addr) { + case 0x3c0: + if (s->ar_flip_flop == 0) { + val &= 0x3f; + s->ar_index = val; + } else { + index = s->ar_index & 0x1f; + switch(index) { + case 0x00 ... 0x0f: + s->ar[index] = val & 0x3f; + break; + case 0x10: + s->ar[index] = val & ~0x10; + break; + case 0x11: + s->ar[index] = val; + break; + case 0x12: + s->ar[index] = val & ~0xc0; + break; + case 0x13: + s->ar[index] = val & ~0xf0; + break; + case 0x14: + s->ar[index] = val & ~0xf0; + break; + default: + break; + } + } + s->ar_flip_flop ^= 1; + break; + case 0x3c2: + s->msr = val & ~0x10; + break; + case 0x3c4: + s->sr_index = val & 7; + break; + case 0x3c5: +#ifdef DEBUG_VGA_REG + printf("vga: write SR%x = 0x%02x\n", s->sr_index, val); +#endif + s->sr[s->sr_index] = val & sr_mask[s->sr_index]; + break; + case 0x3c7: + s->dac_read_index = val; + s->dac_sub_index = 0; + s->dac_state = 3; + break; + case 0x3c8: + s->dac_write_index = val; + s->dac_sub_index = 0; + s->dac_state = 0; + break; + case 0x3c9: + s->dac_cache[s->dac_sub_index] = val; + if (++s->dac_sub_index == 3) { + memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3); + s->dac_sub_index = 0; + s->dac_write_index++; + } + break; + case 0x3ce: + s->gr_index = val & 0x0f; + break; + case 0x3cf: +#ifdef DEBUG_VGA_REG + printf("vga: write GR%x = 0x%02x\n", s->gr_index, val); +#endif + s->gr[s->gr_index] = val & gr_mask[s->gr_index]; + break; + case 0x3b4: + case 0x3d4: + s->cr_index = val; + break; + case 0x3b5: + case 0x3d5: +#ifdef DEBUG_VGA_REG + printf("vga: write CR%x = 0x%02x\n", s->cr_index, val); +#endif + /* handle CR0-7 protection */ + if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) { + /* can always write bit 4 of CR7 */ + if (s->cr_index == 7) + s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10); + return; + } + switch(s->cr_index) { + case 0x01: /* horizontal display end */ + case 0x07: + case 0x09: + case 0x0c: + case 0x0d: + case 0x12: /* veritcal display end */ + s->cr[s->cr_index] = val; + break; + +#ifdef CONFIG_S3VGA + /* S3 registers */ + case 0x2d: + case 0x2e: + case 0x2f: + case 0x30: + /* chip ID, cannot write */ + break; + case 0x31: + /* update start address */ + { + int v; + s->cr[s->cr_index] = val; + v = (val >> 4) & 3; + s->cr[0x69] = (s->cr[69] & ~0x03) | v; + } + break; + case 0x51: + /* update start address */ + { + int v; + s->cr[s->cr_index] = val; + v = val & 3; + s->cr[0x69] = (s->cr[69] & ~0x0c) | (v << 2); + } + break; +#endif + default: + s->cr[s->cr_index] = val; + break; + } +#ifdef DEBUG_S3 + if (s->cr_index >= 0x20) + printf("S3: CR write index=0x%x val=0x%x\n", + s->cr_index, val); +#endif + break; + case 0x3ba: + case 0x3da: + s->fcr = val & 0x10; + break; + } +} + +#ifdef CONFIG_BOCHS_VBE +static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr) +{ + VGAState *s = opaque; + uint32_t val; + val = s->vbe_index; + return val; +} + +static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr) +{ + VGAState *s = opaque; + uint32_t val; + + if (s->vbe_index <= VBE_DISPI_INDEX_NB) + val = s->vbe_regs[s->vbe_index]; + else + val = 0; +#ifdef DEBUG_BOCHS_VBE + printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val); +#endif + return val; +} + +static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val) +{ + VGAState *s = opaque; + s->vbe_index = val; +} + +static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val) +{ + VGAState *s = opaque; + + if (s->vbe_index <= VBE_DISPI_INDEX_NB) { +#ifdef DEBUG_BOCHS_VBE + printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val); +#endif + switch(s->vbe_index) { + case VBE_DISPI_INDEX_ID: + if (val == VBE_DISPI_ID0 || + val == VBE_DISPI_ID1 || + val == VBE_DISPI_ID2) { + s->vbe_regs[s->vbe_index] = val; + } + break; + case VBE_DISPI_INDEX_XRES: + if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) { + s->vbe_regs[s->vbe_index] = val; + } + break; + case VBE_DISPI_INDEX_YRES: + if (val <= VBE_DISPI_MAX_YRES) { + s->vbe_regs[s->vbe_index] = val; + } + break; + case VBE_DISPI_INDEX_BPP: + if (val == 0) + val = 8; + if (val == 4 || val == 8 || val == 15 || + val == 16 || val == 24 || val == 32) { + s->vbe_regs[s->vbe_index] = val; + } + break; + case VBE_DISPI_INDEX_BANK: + val &= s->vbe_bank_mask; + s->vbe_regs[s->vbe_index] = val; + s->bank_offset = (val << 16); + break; + case VBE_DISPI_INDEX_ENABLE: + if (val & VBE_DISPI_ENABLED) { + int h, shift_control; + + s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = + s->vbe_regs[VBE_DISPI_INDEX_XRES]; + s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = + s->vbe_regs[VBE_DISPI_INDEX_YRES]; + s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0; + s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0; + + if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) + s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1; + else + s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] * + ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3); + s->vbe_start_addr = 0; + + /* clear the screen (should be done in BIOS) */ + if (!(val & VBE_DISPI_NOCLEARMEM)) { + memset(s->vram_ptr, 0, + s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset); + } + + /* we initialize the VGA graphic mode (should be done + in BIOS) */ + s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */ + s->cr[0x17] |= 3; /* no CGA modes */ + s->cr[0x13] = s->vbe_line_offset >> 3; + /* width */ + s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1; + /* height */ + h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1; + s->cr[0x12] = h; + s->cr[0x07] = (s->cr[0x07] & ~0x42) | + ((h >> 7) & 0x02) | ((h >> 3) & 0x40); + /* line compare to 1023 */ + s->cr[0x18] = 0xff; + s->cr[0x07] |= 0x10; + s->cr[0x09] |= 0x40; + + if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) { + shift_control = 0; + s->sr[0x01] &= ~8; /* no double line */ + } else { + shift_control = 2; + s->sr[4] |= 0x08; /* set chain 4 mode */ + s->sr[2] |= 0x0f; /* activate all planes */ + } + s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5); + s->cr[0x09] &= ~0x9f; /* no double scan */ + } else { + /* XXX: the bios should do that */ + s->bank_offset = 0; + } + s->vbe_regs[s->vbe_index] = val; + break; + case VBE_DISPI_INDEX_VIRT_WIDTH: + { + int w, h, line_offset; + + if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES]) + return; + w = val; + if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) + line_offset = w >> 1; + else + line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3); + h = s->vram_size / line_offset; + /* XXX: support weird bochs semantics ? */ + if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES]) + return; + s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w; + s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h; + s->vbe_line_offset = line_offset; + } + break; + case VBE_DISPI_INDEX_X_OFFSET: + case VBE_DISPI_INDEX_Y_OFFSET: + { + int x; + s->vbe_regs[s->vbe_index] = val; + s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET]; + x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET]; + if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) + s->vbe_start_addr += x >> 1; + else + s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3); + s->vbe_start_addr >>= 2; + } + break; + default: + break; + } + } +} +#endif + +extern FILE *logfile; +/* called for accesses between 0xa0000 and 0xc0000 */ +uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr) +{ + VGAState *s = opaque; + int memory_map_mode, plane; + uint32_t ret; + + /* convert to VGA memory offset */ + memory_map_mode = (s->gr[6] >> 2) & 3; + addr &= 0x1ffff; + switch(memory_map_mode) { + case 0: + break; + case 1: + if (addr >= 0x10000) + return 0xff; + addr += s->bank_offset; + break; + case 2: + addr -= 0x10000; + if (addr >= 0x8000) + return 0xff; + break; + default: + case 3: + addr -= 0x18000; + if (addr >= 0x8000) + return 0xff; + break; + } + + if (s->sr[4] & 0x08) { + /* chain 4 mode : simplest access */ + ret = s->vram_ptr[addr]; + } else if (s->gr[5] & 0x10) { + /* odd/even mode (aka text mode mapping) */ + plane = (s->gr[4] & 2) | (addr & 1); + ret = s->vram_ptr[((addr & ~1) << 1) | plane]; + } else { + /* standard VGA latched access */ + s->latch = ((uint32_t *)s->vram_ptr)[addr]; + + if (!(s->gr[5] & 0x08)) { + /* read mode 0 */ + plane = s->gr[4]; + ret = GET_PLANE(s->latch, plane); + } else { + /* read mode 1 */ + ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]]; + ret |= ret >> 16; + ret |= ret >> 8; + ret = (~ret) & 0xff; + } + } + return ret; +} + +static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; +#ifdef TARGET_WORDS_BIGENDIAN + v = vga_mem_readb(opaque, addr) << 8; + v |= vga_mem_readb(opaque, addr + 1); +#else + v = vga_mem_readb(opaque, addr); + v |= vga_mem_readb(opaque, addr + 1) << 8; +#endif + return v; +} + +static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr) +{ + uint32_t v; +#ifdef TARGET_WORDS_BIGENDIAN + v = vga_mem_readb(opaque, addr) << 24; + v |= vga_mem_readb(opaque, addr + 1) << 16; + v |= vga_mem_readb(opaque, addr + 2) << 8; + v |= vga_mem_readb(opaque, addr + 3); +#else + v = vga_mem_readb(opaque, addr); + v |= vga_mem_readb(opaque, addr + 1) << 8; + v |= vga_mem_readb(opaque, addr + 2) << 16; + v |= vga_mem_readb(opaque, addr + 3) << 24; +#endif + return v; +} + +/* called for accesses between 0xa0000 and 0xc0000 */ +void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) +{ + VGAState *s = opaque; + int memory_map_mode, plane, write_mode, b, func_select, mask; + uint32_t write_mask, bit_mask, set_mask; + +#ifdef DEBUG_VGA_MEM + printf("vga: [0x%x] = 0x%02x\n", addr, val); +#endif + /* convert to VGA memory offset */ + memory_map_mode = (s->gr[6] >> 2) & 3; + addr &= 0x1ffff; + switch(memory_map_mode) { + case 0: + break; + case 1: + if (addr >= 0x10000) + return; + addr += s->bank_offset; + break; + case 2: + addr -= 0x10000; + if (addr >= 0x8000) + return; + break; + default: + case 3: + addr -= 0x18000; + if (addr >= 0x8000) + return; + break; + } + + if (s->sr[4] & 0x08) { + /* chain 4 mode : simplest access */ + plane = addr & 3; + mask = (1 << plane); + if (s->sr[2] & mask) { + s->vram_ptr[addr] = val; +#ifdef DEBUG_VGA_MEM + printf("vga: chain4: [0x%x]\n", addr); +#endif + s->plane_updated |= mask; /* only used to detect font change */ + cpu_physical_memory_set_dirty(s->vram_offset + addr); + } + } else if (s->gr[5] & 0x10) { + /* odd/even mode (aka text mode mapping) */ + plane = (s->gr[4] & 2) | (addr & 1); + mask = (1 << plane); + if (s->sr[2] & mask) { + addr = ((addr & ~1) << 1) | plane; + s->vram_ptr[addr] = val; +#ifdef DEBUG_VGA_MEM + printf("vga: odd/even: [0x%x]\n", addr); +#endif + s->plane_updated |= mask; /* only used to detect font change */ + cpu_physical_memory_set_dirty(s->vram_offset + addr); + } + } else { + /* standard VGA latched access */ + write_mode = s->gr[5] & 3; + switch(write_mode) { + default: + case 0: + /* rotate */ + b = s->gr[3] & 7; + val = ((val >> b) | (val << (8 - b))) & 0xff; + val |= val << 8; + val |= val << 16; + + /* apply set/reset mask */ + set_mask = mask16[s->gr[1]]; + val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask); + bit_mask = s->gr[8]; + break; + case 1: + val = s->latch; + goto do_write; + case 2: + val = mask16[val & 0x0f]; + bit_mask = s->gr[8]; + break; + case 3: + /* rotate */ + b = s->gr[3] & 7; + val = (val >> b) | (val << (8 - b)); + + bit_mask = s->gr[8] & val; + val = mask16[s->gr[0]]; + break; + } + + /* apply logical operation */ + func_select = s->gr[3] >> 3; + switch(func_select) { + case 0: + default: + /* nothing to do */ + break; + case 1: + /* and */ + val &= s->latch; + break; + case 2: + /* or */ + val |= s->latch; + break; + case 3: + /* xor */ + val ^= s->latch; + break; + } + + /* apply bit mask */ + bit_mask |= bit_mask << 8; + bit_mask |= bit_mask << 16; + val = (val & bit_mask) | (s->latch & ~bit_mask); + + do_write: + /* mask data according to sr[2] */ + mask = s->sr[2]; + s->plane_updated |= mask; /* only used to detect font change */ + write_mask = mask16[mask]; + ((uint32_t *)s->vram_ptr)[addr] = + (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) | + (val & write_mask); +#ifdef DEBUG_VGA_MEM + printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n", + addr * 4, write_mask, val); +#endif + cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2)); + } +} + +static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + vga_mem_writeb(opaque, addr, (val >> 8) & 0xff); + vga_mem_writeb(opaque, addr + 1, val & 0xff); +#else + vga_mem_writeb(opaque, addr, val & 0xff); + vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff); +#endif +} + +static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) +{ +#ifdef TARGET_WORDS_BIGENDIAN + vga_mem_writeb(opaque, addr, (val >> 24) & 0xff); + vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff); + vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff); + vga_mem_writeb(opaque, addr + 3, val & 0xff); +#else + vga_mem_writeb(opaque, addr, val & 0xff); + vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff); + vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff); + vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff); +#endif +} + +typedef void vga_draw_glyph8_func(uint8_t *d, int linesize, + const uint8_t *font_ptr, int h, + uint32_t fgcol, uint32_t bgcol); +typedef void vga_draw_glyph9_func(uint8_t *d, int linesize, + const uint8_t *font_ptr, int h, + uint32_t fgcol, uint32_t bgcol, int dup9); +typedef void vga_draw_line_func(VGAState *s1, uint8_t *d, + const uint8_t *s, int width); + +static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b) +{ + return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6); +} + +static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b) +{ + return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3); +} + +static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b) +{ + return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); +} + +static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b) +{ + return (r << 16) | (g << 8) | b; +} + +#define DEPTH 8 +#include "vga_template.h" + +#define DEPTH 15 +#include "vga_template.h" + +#define DEPTH 16 +#include "vga_template.h" + +#define DEPTH 32 +#include "vga_template.h" + +static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b) +{ + unsigned int col; + col = rgb_to_pixel8(r, g, b); + col |= col << 8; + col |= col << 16; + return col; +} + +static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b) +{ + unsigned int col; + col = rgb_to_pixel15(r, g, b); + col |= col << 16; + return col; +} + +static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b) +{ + unsigned int col; + col = rgb_to_pixel16(r, g, b); + col |= col << 16; + return col; +} + +static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b) +{ + unsigned int col; + col = rgb_to_pixel32(r, g, b); + return col; +} + +/* return true if the palette was modified */ +static int update_palette16(VGAState *s) +{ + int full_update, i; + uint32_t v, col, *palette; + + full_update = 0; + palette = s->last_palette; + for(i = 0; i < 16; i++) { + v = s->ar[i]; + if (s->ar[0x10] & 0x80) + v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf); + else + v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f); + v = v * 3; + col = s->rgb_to_pixel(c6_to_8(s->palette[v]), + c6_to_8(s->palette[v + 1]), + c6_to_8(s->palette[v + 2])); + if (col != palette[i]) { + full_update = 1; + palette[i] = col; + } + } + return full_update; +} + +/* return true if the palette was modified */ +static int update_palette256(VGAState *s) +{ + int full_update, i; + uint32_t v, col, *palette; + + full_update = 0; + palette = s->last_palette; + v = 0; + for(i = 0; i < 256; i++) { + col = s->rgb_to_pixel(c6_to_8(s->palette[v]), + c6_to_8(s->palette[v + 1]), + c6_to_8(s->palette[v + 2])); + if (col != palette[i]) { + full_update = 1; + palette[i] = col; + } + v += 3; + } + return full_update; +} + +static void vga_get_offsets(VGAState *s, + uint32_t *pline_offset, + uint32_t *pstart_addr) +{ + uint32_t start_addr, line_offset; +#ifdef CONFIG_BOCHS_VBE + if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { + line_offset = s->vbe_line_offset; + start_addr = s->vbe_start_addr; + } else +#endif + { + /* compute line_offset in bytes */ + line_offset = s->cr[0x13]; +#ifdef CONFIG_S3VGA + { + uinr32_t v; + v = (s->cr[0x51] >> 4) & 3; /* S3 extension */ + if (v == 0) + v = (s->cr[0x43] >> 2) & 1; /* S3 extension */ + line_offset |= (v << 8); + } +#endif + line_offset <<= 3; + + /* starting address */ + start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8); +#ifdef CONFIG_S3VGA + start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */ +#endif + } + *pline_offset = line_offset; + *pstart_addr = start_addr; +} + +/* update start_addr and line_offset. Return TRUE if modified */ +static int update_basic_params(VGAState *s) +{ + int full_update; + uint32_t start_addr, line_offset, line_compare; + + full_update = 0; + + s->get_offsets(s, &line_offset, &start_addr); + /* line compare */ + line_compare = s->cr[0x18] | + ((s->cr[0x07] & 0x10) << 4) | + ((s->cr[0x09] & 0x40) << 3); + + if (line_offset != s->line_offset || + start_addr != s->start_addr || + line_compare != s->line_compare) { + s->line_offset = line_offset; + s->start_addr = start_addr; + s->line_compare = line_compare; + full_update = 1; + } + return full_update; +} + +static inline int get_depth_index(int depth) +{ + switch(depth) { + default: + case 8: + return 0; + case 15: + return 1; + case 16: + return 2; + case 32: + return 3; + } +} + +static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = { + vga_draw_glyph8_8, + vga_draw_glyph8_16, + vga_draw_glyph8_16, + vga_draw_glyph8_32, +}; + +static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = { + vga_draw_glyph16_8, + vga_draw_glyph16_16, + vga_draw_glyph16_16, + vga_draw_glyph16_32, +}; + +static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = { + vga_draw_glyph9_8, + vga_draw_glyph9_16, + vga_draw_glyph9_16, + vga_draw_glyph9_32, +}; + +static const uint8_t cursor_glyph[32 * 4] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +}; + +/* + * Text mode update + * Missing: + * - double scan + * - double width + * - underline + * - flashing + */ +static void vga_draw_text(VGAState *s, int full_update) +{ + int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr; + int cx_min, cx_max, linesize, x_incr; + uint32_t offset, fgcol, bgcol, v, cursor_offset; + uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr; + const uint8_t *font_ptr, *font_base[2]; + int dup9, line_offset, depth_index; + uint32_t *palette; + uint32_t *ch_attr_ptr; + vga_draw_glyph8_func *vga_draw_glyph8; + vga_draw_glyph9_func *vga_draw_glyph9; + + full_update |= update_palette16(s); + palette = s->last_palette; + + /* compute font data address (in plane 2) */ + v = s->sr[3]; + offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2; + if (offset != s->font_offsets[0]) { + s->font_offsets[0] = offset; + full_update = 1; + } + font_base[0] = s->vram_ptr + offset; + + offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2; + font_base[1] = s->vram_ptr + offset; + if (offset != s->font_offsets[1]) { + s->font_offsets[1] = offset; + full_update = 1; + } + if (s->plane_updated & (1 << 2)) { + /* if the plane 2 was modified since the last display, it + indicates the font may have been modified */ + s->plane_updated = 0; + full_update = 1; + } + full_update |= update_basic_params(s); + + line_offset = s->line_offset; + s1 = s->vram_ptr + (s->start_addr * 4); + + /* total width & height */ + cheight = (s->cr[9] & 0x1f) + 1; + cw = 8; + if (!(s->sr[1] & 0x01)) + cw = 9; + if (s->sr[1] & 0x08) + cw = 16; /* NOTE: no 18 pixel wide */ + x_incr = cw * ((s->ds->depth + 7) >> 3); + width = (s->cr[0x01] + 1); + if (s->cr[0x06] == 100) { + /* ugly hack for CGA 160x100x16 - explain me the logic */ + height = 100; + } else { + height = s->cr[0x12] | + ((s->cr[0x07] & 0x02) << 7) | + ((s->cr[0x07] & 0x40) << 3); + height = (height + 1) / cheight; + } + if ((height * width) > CH_ATTR_SIZE) { + /* better than nothing: exit if transient size is too big */ + return; + } + + if (width != s->last_width || height != s->last_height || + cw != s->last_cw || cheight != s->last_ch) { + s->last_scr_width = width * cw; + s->last_scr_height = height * cheight; + dpy_resize(s->ds, s->last_scr_width, s->last_scr_height); + s->last_width = width; + s->last_height = height; + s->last_ch = cheight; + s->last_cw = cw; + full_update = 1; + } + cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr; + if (cursor_offset != s->cursor_offset || + s->cr[0xa] != s->cursor_start || + s->cr[0xb] != s->cursor_end) { + /* if the cursor position changed, we update the old and new + chars */ + if (s->cursor_offset < CH_ATTR_SIZE) + s->last_ch_attr[s->cursor_offset] = -1; + if (cursor_offset < CH_ATTR_SIZE) + s->last_ch_attr[cursor_offset] = -1; + s->cursor_offset = cursor_offset; + s->cursor_start = s->cr[0xa]; + s->cursor_end = s->cr[0xb]; + } + cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4; + + depth_index = get_depth_index(s->ds->depth); + if (cw == 16) + vga_draw_glyph8 = vga_draw_glyph16_table[depth_index]; + else + vga_draw_glyph8 = vga_draw_glyph8_table[depth_index]; + vga_draw_glyph9 = vga_draw_glyph9_table[depth_index]; + + dest = s->ds->data; + linesize = s->ds->linesize; + ch_attr_ptr = s->last_ch_attr; + for(cy = 0; cy < height; cy++) { + d1 = dest; + src = s1; + cx_min = width; + cx_max = -1; + for(cx = 0; cx < width; cx++) { + ch_attr = *(uint16_t *)src; + if (full_update || ch_attr != *ch_attr_ptr) { + if (cx < cx_min) + cx_min = cx; + if (cx > cx_max) + cx_max = cx; + *ch_attr_ptr = ch_attr; +#ifdef WORDS_BIGENDIAN + ch = ch_attr >> 8; + cattr = ch_attr & 0xff; +#else + ch = ch_attr & 0xff; + cattr = ch_attr >> 8; +#endif + font_ptr = font_base[(cattr >> 3) & 1]; + font_ptr += 32 * 4 * ch; + bgcol = palette[cattr >> 4]; + fgcol = palette[cattr & 0x0f]; + if (cw != 9) { + vga_draw_glyph8(d1, linesize, + font_ptr, cheight, fgcol, bgcol); + } else { + dup9 = 0; + if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04)) + dup9 = 1; + vga_draw_glyph9(d1, linesize, + font_ptr, cheight, fgcol, bgcol, dup9); + } + if (src == cursor_ptr && + !(s->cr[0x0a] & 0x20)) { + int line_start, line_last, h; + /* draw the cursor */ + line_start = s->cr[0x0a] & 0x1f; + line_last = s->cr[0x0b] & 0x1f; + /* XXX: check that */ + if (line_last > cheight - 1) + line_last = cheight - 1; + if (line_last >= line_start && line_start < cheight) { + h = line_last - line_start + 1; + d = d1 + linesize * line_start; + if (cw != 9) { + vga_draw_glyph8(d, linesize, + cursor_glyph, h, fgcol, bgcol); + } else { + vga_draw_glyph9(d, linesize, + cursor_glyph, h, fgcol, bgcol, 1); + } + } + } + } + d1 += x_incr; + src += 4; + ch_attr_ptr++; + } + if (cx_max != -1) { + dpy_update(s->ds, cx_min * cw, cy * cheight, + (cx_max - cx_min + 1) * cw, cheight); + } + dest += linesize * cheight; + s1 += line_offset; + } +} + +enum { + VGA_DRAW_LINE2, + VGA_DRAW_LINE2D2, + VGA_DRAW_LINE4, + VGA_DRAW_LINE4D2, + VGA_DRAW_LINE8D2, + VGA_DRAW_LINE8, + VGA_DRAW_LINE15, + VGA_DRAW_LINE16, + VGA_DRAW_LINE24, + VGA_DRAW_LINE32, + VGA_DRAW_LINE_NB, +}; + +static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = { + vga_draw_line2_8, + vga_draw_line2_16, + vga_draw_line2_16, + vga_draw_line2_32, + + vga_draw_line2d2_8, + vga_draw_line2d2_16, + vga_draw_line2d2_16, + vga_draw_line2d2_32, + + vga_draw_line4_8, + vga_draw_line4_16, + vga_draw_line4_16, + vga_draw_line4_32, + + vga_draw_line4d2_8, + vga_draw_line4d2_16, + vga_draw_line4d2_16, + vga_draw_line4d2_32, + + vga_draw_line8d2_8, + vga_draw_line8d2_16, + vga_draw_line8d2_16, + vga_draw_line8d2_32, + + vga_draw_line8_8, + vga_draw_line8_16, + vga_draw_line8_16, + vga_draw_line8_32, + + vga_draw_line15_8, + vga_draw_line15_15, + vga_draw_line15_16, + vga_draw_line15_32, + + vga_draw_line16_8, + vga_draw_line16_15, + vga_draw_line16_16, + vga_draw_line16_32, + + vga_draw_line24_8, + vga_draw_line24_15, + vga_draw_line24_16, + vga_draw_line24_32, + + vga_draw_line32_8, + vga_draw_line32_15, + vga_draw_line32_16, + vga_draw_line32_32, +}; + +static int vga_get_bpp(VGAState *s) +{ + int ret; +#ifdef CONFIG_BOCHS_VBE + if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) { + ret = s->vbe_regs[VBE_DISPI_INDEX_BPP]; + } else +#endif + { + ret = 0; + } + return ret; +} + +static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight) +{ + int width, height; + + width = (s->cr[0x01] + 1) * 8; + height = s->cr[0x12] | + ((s->cr[0x07] & 0x02) << 7) | + ((s->cr[0x07] & 0x40) << 3); + height = (height + 1); + *pwidth = width; + *pheight = height; +} + +void vga_invalidate_scanlines(VGAState *s, int y1, int y2) +{ + int y; + if (y1 >= VGA_MAX_HEIGHT) + return; + if (y2 >= VGA_MAX_HEIGHT) + y2 = VGA_MAX_HEIGHT; + for(y = y1; y < y2; y++) { + s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f); + } +} + +/* + * graphic modes + */ +static void vga_draw_graphic(VGAState *s, int full_update) +{ + int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask; + int width, height, shift_control, line_offset, page0, page1, bwidth; + int disp_width, multi_scan, multi_run; + uint8_t *d; + uint32_t v, addr1, addr; + vga_draw_line_func *vga_draw_line; + + full_update |= update_basic_params(s); + + s->get_resolution(s, &width, &height); + disp_width = width; + + shift_control = (s->gr[0x05] >> 5) & 3; + double_scan = (s->cr[0x09] >> 7); + if (shift_control != 1) { + multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1; + } else { + /* in CGA modes, multi_scan is ignored */ + /* XXX: is it correct ? */ + multi_scan = double_scan; + } + multi_run = multi_scan; + if (shift_control != s->shift_control || + double_scan != s->double_scan) { + full_update = 1; + s->shift_control = shift_control; + s->double_scan = double_scan; + } + + if (shift_control == 0) { + full_update |= update_palette16(s); + if (s->sr[0x01] & 8) { + v = VGA_DRAW_LINE4D2; + disp_width <<= 1; + } else { + v = VGA_DRAW_LINE4; + } + } else if (shift_control == 1) { + full_update |= update_palette16(s); + if (s->sr[0x01] & 8) { + v = VGA_DRAW_LINE2D2; + disp_width <<= 1; + } else { + v = VGA_DRAW_LINE2; + } + } else { + switch(s->get_bpp(s)) { + default: + case 0: + full_update |= update_palette256(s); + v = VGA_DRAW_LINE8D2; + break; + case 8: + full_update |= update_palette256(s); + v = VGA_DRAW_LINE8; + break; + case 15: + v = VGA_DRAW_LINE15; + break; + case 16: + v = VGA_DRAW_LINE16; + break; + case 24: + v = VGA_DRAW_LINE24; + break; + case 32: + v = VGA_DRAW_LINE32; + break; + } + } + vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)]; + + if (disp_width != s->last_width || + height != s->last_height) { + dpy_resize(s->ds, disp_width, height); + s->last_scr_width = disp_width; + s->last_scr_height = height; + s->last_width = disp_width; + s->last_height = height; + full_update = 1; + } + if (s->cursor_invalidate) + s->cursor_invalidate(s); + + line_offset = s->line_offset; +#if 0 + printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n", + width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]); +#endif + addr1 = (s->start_addr * 4); + bwidth = width * 4; + y_start = -1; + page_min = 0x7fffffff; + page_max = -1; + d = s->ds->data; + linesize = s->ds->linesize; + y1 = 0; + for(y = 0; y < height; y++) { + addr = addr1; + if (!(s->cr[0x17] & 1)) { + int shift; + /* CGA compatibility handling */ + shift = 14 + ((s->cr[0x17] >> 6) & 1); + addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift); + } + if (!(s->cr[0x17] & 2)) { + addr = (addr & ~0x8000) | ((y1 & 2) << 14); + } + page0 = s->vram_offset + (addr & TARGET_PAGE_MASK); + page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK); + update = full_update | cpu_physical_memory_is_dirty(page0) | + cpu_physical_memory_is_dirty(page1); + if ((page1 - page0) > TARGET_PAGE_SIZE) { + /* if wide line, can use another page */ + update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE); + } + /* explicit invalidation for the hardware cursor */ + update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1; + if (update) { + if (y_start < 0) + y_start = y; + if (page0 < page_min) + page_min = page0; + if (page1 > page_max) + page_max = page1; + vga_draw_line(s, d, s->vram_ptr + addr, width); + if (s->cursor_draw_line) + s->cursor_draw_line(s, d, y); + } else { + if (y_start >= 0) { + /* flush to display */ + dpy_update(s->ds, 0, y_start, + disp_width, y - y_start); + y_start = -1; + } + } + if (!multi_run) { + mask = (s->cr[0x17] & 3) ^ 3; + if ((y1 & mask) == mask) + addr1 += line_offset; + y1++; + multi_run = multi_scan; + } else { + multi_run--; + } + /* line compare acts on the displayed lines */ + if (y == s->line_compare) + addr1 = 0; + d += linesize; + } + if (y_start >= 0) { + /* flush to display */ + dpy_update(s->ds, 0, y_start, + disp_width, y - y_start); + } + /* reset modified pages */ + if (page_max != -1) { + cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE); + } + memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4); +} + +static void vga_draw_blank(VGAState *s, int full_update) +{ + int i, w, val; + uint8_t *d; + + if (!full_update) + return; + if (s->last_scr_width <= 0 || s->last_scr_height <= 0) + return; + if (s->ds->depth == 8) + val = s->rgb_to_pixel(0, 0, 0); + else + val = 0; + w = s->last_scr_width * ((s->ds->depth + 7) >> 3); + d = s->ds->data; + for(i = 0; i < s->last_scr_height; i++) { + memset(d, val, w); + d += s->ds->linesize; + } + dpy_update(s->ds, 0, 0, + s->last_scr_width, s->last_scr_height); +} + +#define GMODE_TEXT 0 +#define GMODE_GRAPH 1 +#define GMODE_BLANK 2 + +void vga_update_display(void) +{ + VGAState *s = vga_state; + int full_update, graphic_mode; + + if (s->ds->depth == 0) { + /* nothing to do */ + } else { + switch(s->ds->depth) { + case 8: + s->rgb_to_pixel = rgb_to_pixel8_dup; + break; + case 15: + s->rgb_to_pixel = rgb_to_pixel15_dup; + break; + default: + case 16: + s->rgb_to_pixel = rgb_to_pixel16_dup; + break; + case 32: + s->rgb_to_pixel = rgb_to_pixel32_dup; + break; + } + + full_update = 0; + if (!(s->ar_index & 0x20)) { + graphic_mode = GMODE_BLANK; + } else { + graphic_mode = s->gr[6] & 1; + } + if (graphic_mode != s->graphic_mode) { + s->graphic_mode = graphic_mode; + full_update = 1; + } + switch(graphic_mode) { + case GMODE_TEXT: + vga_draw_text(s, full_update); + break; + case GMODE_GRAPH: + vga_draw_graphic(s, full_update); + break; + case GMODE_BLANK: + default: + vga_draw_blank(s, full_update); + break; + } + } +} + +/* force a full display refresh */ +void vga_invalidate_display(void) +{ + VGAState *s = vga_state; + + s->last_width = -1; + s->last_height = -1; +} + +static void vga_reset(VGAState *s) +{ + memset(s, 0, sizeof(VGAState)); +#ifdef CONFIG_S3VGA + /* chip ID for 8c968 */ + s->cr[0x2d] = 0x88; + s->cr[0x2e] = 0xb0; + s->cr[0x2f] = 0x01; /* XXX: check revision code */ + s->cr[0x30] = 0xe1; +#endif + s->graphic_mode = -1; /* force full update */ +} + +static CPUReadMemoryFunc *vga_mem_read[3] = { + vga_mem_readb, + vga_mem_readw, + vga_mem_readl, +}; + +static CPUWriteMemoryFunc *vga_mem_write[3] = { + vga_mem_writeb, + vga_mem_writew, + vga_mem_writel, +}; + +static void vga_save(QEMUFile *f, void *opaque) +{ + VGAState *s = opaque; + int i; + + qemu_put_be32s(f, &s->latch); + qemu_put_8s(f, &s->sr_index); + qemu_put_buffer(f, s->sr, 8); + qemu_put_8s(f, &s->gr_index); + qemu_put_buffer(f, s->gr, 16); + qemu_put_8s(f, &s->ar_index); + qemu_put_buffer(f, s->ar, 21); + qemu_put_be32s(f, &s->ar_flip_flop); + qemu_put_8s(f, &s->cr_index); + qemu_put_buffer(f, s->cr, 256); + qemu_put_8s(f, &s->msr); + qemu_put_8s(f, &s->fcr); + qemu_put_8s(f, &s->st00); + qemu_put_8s(f, &s->st01); + + qemu_put_8s(f, &s->dac_state); + qemu_put_8s(f, &s->dac_sub_index); + qemu_put_8s(f, &s->dac_read_index); + qemu_put_8s(f, &s->dac_write_index); + qemu_put_buffer(f, s->dac_cache, 3); + qemu_put_buffer(f, s->palette, 768); + + qemu_put_be32s(f, &s->bank_offset); +#ifdef CONFIG_BOCHS_VBE + qemu_put_byte(f, 1); + qemu_put_be16s(f, &s->vbe_index); + for(i = 0; i < VBE_DISPI_INDEX_NB; i++) + qemu_put_be16s(f, &s->vbe_regs[i]); + qemu_put_be32s(f, &s->vbe_start_addr); + qemu_put_be32s(f, &s->vbe_line_offset); + qemu_put_be32s(f, &s->vbe_bank_mask); +#else + qemu_put_byte(f, 0); +#endif +} + +static int vga_load(QEMUFile *f, void *opaque, int version_id) +{ + VGAState *s = opaque; + int is_vbe, i; + + if (version_id != 1) + return -EINVAL; + + qemu_get_be32s(f, &s->latch); + qemu_get_8s(f, &s->sr_index); + qemu_get_buffer(f, s->sr, 8); + qemu_get_8s(f, &s->gr_index); + qemu_get_buffer(f, s->gr, 16); + qemu_get_8s(f, &s->ar_index); + qemu_get_buffer(f, s->ar, 21); + qemu_get_be32s(f, &s->ar_flip_flop); + qemu_get_8s(f, &s->cr_index); + qemu_get_buffer(f, s->cr, 256); + qemu_get_8s(f, &s->msr); + qemu_get_8s(f, &s->fcr); + qemu_get_8s(f, &s->st00); + qemu_get_8s(f, &s->st01); + + qemu_get_8s(f, &s->dac_state); + qemu_get_8s(f, &s->dac_sub_index); + qemu_get_8s(f, &s->dac_read_index); + qemu_get_8s(f, &s->dac_write_index); + qemu_get_buffer(f, s->dac_cache, 3); + qemu_get_buffer(f, s->palette, 768); + + qemu_get_be32s(f, &s->bank_offset); + is_vbe = qemu_get_byte(f); +#ifdef CONFIG_BOCHS_VBE + if (!is_vbe) + return -EINVAL; + qemu_get_be16s(f, &s->vbe_index); + for(i = 0; i < VBE_DISPI_INDEX_NB; i++) + qemu_get_be16s(f, &s->vbe_regs[i]); + qemu_get_be32s(f, &s->vbe_start_addr); + qemu_get_be32s(f, &s->vbe_line_offset); + qemu_get_be32s(f, &s->vbe_bank_mask); +#else + if (is_vbe) + return -EINVAL; +#endif + + /* force refresh */ + s->graphic_mode = -1; + return 0; +} + +static void vga_map(PCIDevice *pci_dev, int region_num, + uint32_t addr, uint32_t size, int type) +{ + VGAState *s = vga_state; + + cpu_register_physical_memory(addr, s->vram_size, s->vram_offset); +} + +/* do the same job as vgabios before vgabios get ready */ +void vga_bios_init(VGAState *s) +{ + uint8_t palette_model[192] = { + 0, 0, 0, 0, 0, 170, 0, 170, 0, 0, 170, 170, 170, 0, 0, 170, + 0, 170, 170, 85, 0, 170, 170, 170, 85, 85, 85, 85, 85, 255, 85, 255, + 85, 85, 255, 255, 255, 85, 85, 255, 85, 255, 255, 255, 85, 255, 255, 255, + 0, 21, 0, 0, 21, 42, 0, 63, 0, 0, 63, 42, 42, 21, 0, 42, + 21, 42, 42, 63, 0, 42, 63, 42, 0, 21, 21, 0, 21, 63, 0, 63, + 21, 0, 63, 63, 42, 21, 21, 42, 21, 63, 42, 63, 21, 42, 63, 63, + 21, 0, 0, 21, 0, 42, 21, 42, 0, 21, 42, 42, 63, 0, 0, 63, + 0, 42, 63, 42, 0, 63, 42, 42, 21, 0, 21, 21, 0, 63, 21, 42, + 21, 21, 42, 63, 63, 0, 21, 63, 0, 63, 63, 42, 21, 63, 42, 63, + 21, 21, 0, 21, 21, 42, 21, 63, 0, 21, 63, 42, 63, 21, 0, 63, + 21, 42, 63, 63, 0, 63, 63, 42, 21, 21, 21, 21, 21, 63, 21, 63, + 21, 21, 63, 63, 63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63 + }; + + s->latch = 0; + + s->sr_index = 3; + s->sr[0] = 3; + s->sr[1] = 0; + s->sr[2] = 3; + s->sr[3] = 0; + s->sr[4] = 2; + s->sr[5] = 0; + s->sr[6] = 0; + s->sr[7] = 0; + + s->gr_index = 5; + s->gr[0] = 0; + s->gr[1] = 0; + s->gr[2] = 0; + s->gr[3] = 0; + s->gr[4] = 0; + s->gr[5] = 16; + s->gr[6] = 14; + s->gr[7] = 15; + s->gr[8] = 255; + + /*changed by out 0x03c0*/ + s->ar_index = 32; + s->ar[0] = 0; + s->ar[1] = 1; + s->ar[2] = 2; + s->ar[3] = 3; + s->ar[4] = 4; + s->ar[5] = 5; + s->ar[6] = 6; + s->ar[7] = 7; + s->ar[8] = 8; + s->ar[9] = 9; + s->ar[10] = 10; + s->ar[11] = 11; + s->ar[12] = 12; + s->ar[13] = 13; + s->ar[14] = 14; + s->ar[15] = 15; + s->ar[16] = 12; + s->ar[17] = 0; + s->ar[18] = 15; + s->ar[19] = 8; + s->ar[20] = 0; + + s->ar_flip_flop = 1; + + s->cr_index = 15; + s->cr[0] = 95; + s->cr[1] = 79; + s->cr[2] = 80; + s->cr[3] = 130; + s->cr[4] = 85; + s->cr[5] = 129; + s->cr[6] = 191; + s->cr[7] = 31; + s->cr[8] = 0; + s->cr[9] = 79; + s->cr[10] = 14; + s->cr[11] = 15; + s->cr[12] = 0; + s->cr[13] = 0; + s->cr[14] = 5; + s->cr[15] = 160; + s->cr[16] = 156; + s->cr[17] = 142; + s->cr[18] = 143; + s->cr[19] = 40; + s->cr[20] = 31; + s->cr[21] = 150; + s->cr[22] = 185; + s->cr[23] = 163; + s->cr[24] = 255; + + s->msr = 103; + s->fcr = 0; + s->st00 = 0; + s->st01 = 0; + + /*dac_* & platte will be initialized by os through out 0x03c8 & out 0c03c9(1:3) */ + s->dac_state = 0; + s->dac_sub_index = 0; + s->dac_read_index = 0; + s->dac_write_index = 16; + s->dac_cache[0] = 255; + s->dac_cache[1] = 255; + s->dac_cache[2] = 255; + + /*platte*/ + memcpy(s->palette, palette_model, 192); + + s->bank_offset= 0; + s->graphic_mode = -1; + + /* TODO:add vbe support if enable it */ + + FILE *qemuf = fopen("/etc/xen/qemu-vgaram-bin", "rb"); + if (!qemuf) { + fprintf(logfile, "open qemu vgaram binary failed!\n"); + } else { + /*load vram contents, else vga console can't boot */ + qemu_get_buffer(qemuf, s->vram_ptr, 256*1024); + + fclose(qemuf); + } + +} + +void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, + unsigned long vga_ram_offset, int vga_ram_size) +{ + int i, j, v, b; + + for(i = 0;i < 256; i++) { + v = 0; + for(j = 0; j < 8; j++) { + v |= ((i >> j) & 1) << (j * 4); + } + expand4[i] = v; + + v = 0; + for(j = 0; j < 4; j++) { + v |= ((i >> (2 * j)) & 3) << (j * 4); + } + expand2[i] = v; + } + for(i = 0; i < 16; i++) { + v = 0; + for(j = 0; j < 4; j++) { + b = ((i >> j) & 1); + v |= b << (2 * j); + v |= b << (2 * j + 1); + } + expand4to8[i] = v; + } + + vga_reset(s); + + /* qemu's vga mem is not detached from phys_ram_base and can cause DM abort + * when guest write vga mem, so allocate a new one */ + s->vram_ptr = qemu_mallocz(256 * 1024); + + s->vram_offset = vga_ram_offset; + s->vram_size = vga_ram_size; + s->ds = ds; + s->get_bpp = vga_get_bpp; + s->get_offsets = vga_get_offsets; + s->get_resolution = vga_get_resolution; + /* XXX: currently needed for display */ + vga_state = s; +} + + +int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, + unsigned long vga_ram_offset, int vga_ram_size) +{ + VGAState *s; + + s = qemu_mallocz(sizeof(VGAState)); + if (!s) + return -1; + + vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size); + + register_savevm("vga", 0, 1, vga_save, vga_load, s); + + register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s); + + register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s); + register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s); + register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s); + register_ioport_write(0x3da, 1, 1, vga_ioport_write, s); + + register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s); + + register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s); + register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s); + register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s); + register_ioport_read(0x3da, 1, 1, vga_ioport_read, s); + s->bank_offset = 0; + +#ifdef CONFIG_BOCHS_VBE + s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0; + s->vbe_bank_mask = ((s->vram_size >> 16) - 1); +#if defined (TARGET_I386) + register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s); + register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s); + + register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s); + register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s); + + /* old Bochs IO ports */ + register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s); + register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s); + + register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s); + register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s); +#else + register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s); + register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s); + + register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s); + register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s); +#endif +#endif /* CONFIG_BOCHS_VBE */ + + vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s); + cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, + vga_io_memory); + + if (bus) { + PCIDevice *d; + uint8_t *pci_conf; + + d = pci_register_device(bus, "VGA", + sizeof(PCIDevice), + -1, NULL, NULL); + pci_conf = d->config; + pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID) + pci_conf[0x01] = 0x12; + pci_conf[0x02] = 0x11; + pci_conf[0x03] = 0x11; + pci_conf[0x0a] = 0x00; // VGA controller + pci_conf[0x0b] = 0x03; + pci_conf[0x0e] = 0x00; // header_type + + /* XXX: vga_ram_size must be a power of two */ + pci_register_io_region(d, 0, vga_ram_size, + PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map); + } else { +#ifdef CONFIG_BOCHS_VBE + /* XXX: use optimized standard vga accesses */ + cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS, + vga_ram_size, vga_ram_offset); +#endif + } + + vga_bios_init(s); + return 0; +} + +/********************************************************/ +/* vga screen dump */ + +static int vga_save_w, vga_save_h; + +static void vga_save_dpy_update(DisplayState *s, + int x, int y, int w, int h) +{ +} + +static void vga_save_dpy_resize(DisplayState *s, int w, int h) +{ + s->linesize = w * 4; + s->data = qemu_malloc(h * s->linesize); + vga_save_w = w; + vga_save_h = h; +} + +static void vga_save_dpy_refresh(DisplayState *s) +{ +} + +static int ppm_save(const char *filename, uint8_t *data, + int w, int h, int linesize) +{ + FILE *f; + uint8_t *d, *d1; + unsigned int v; + int y, x; + + f = fopen(filename, "wb"); + if (!f) + return -1; + fprintf(f, "P6\n%d %d\n%d\n", + w, h, 255); + d1 = data; + for(y = 0; y < h; y++) { + d = d1; + for(x = 0; x < w; x++) { + v = *(uint32_t *)d; + fputc((v >> 16) & 0xff, f); + fputc((v >> 8) & 0xff, f); + fputc((v) & 0xff, f); + d += 4; + } + d1 += linesize; + } + fclose(f); + return 0; +} + +/* save the vga display in a PPM image even if no display is + available */ +void vga_screen_dump(const char *filename) +{ + VGAState *s = vga_state; + DisplayState *saved_ds, ds1, *ds = &ds1; + + /* XXX: this is a little hackish */ + vga_invalidate_display(); + saved_ds = s->ds; + + memset(ds, 0, sizeof(DisplayState)); + ds->dpy_update = vga_save_dpy_update; + ds->dpy_resize = vga_save_dpy_resize; + ds->dpy_refresh = vga_save_dpy_refresh; + ds->depth = 32; + + s->ds = ds; + s->graphic_mode = -1; + vga_update_display(); + + if (ds->data) { + ppm_save(filename, ds->data, vga_save_w, vga_save_h, + s->ds->linesize); + qemu_free(ds->data); + } + s->ds = saved_ds; +} diff --git a/tools/ioemu/hw/vga_int.h b/tools/ioemu/hw/vga_int.h new file mode 100644 index 0000000000..316688265b --- /dev/null +++ b/tools/ioemu/hw/vga_int.h @@ -0,0 +1,168 @@ +/* + * QEMU internal VGA defines. + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#define MSR_COLOR_EMULATION 0x01 +#define MSR_PAGE_SELECT 0x20 + +#define ST01_V_RETRACE 0x08 +#define ST01_DISP_ENABLE 0x01 + +/* bochs VBE support */ +//#define CONFIG_BOCHS_VBE + +#define VBE_DISPI_MAX_XRES 1024 +#define VBE_DISPI_MAX_YRES 768 + +#define VBE_DISPI_INDEX_ID 0x0 +#define VBE_DISPI_INDEX_XRES 0x1 +#define VBE_DISPI_INDEX_YRES 0x2 +#define VBE_DISPI_INDEX_BPP 0x3 +#define VBE_DISPI_INDEX_ENABLE 0x4 +#define VBE_DISPI_INDEX_BANK 0x5 +#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 +#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 +#define VBE_DISPI_INDEX_X_OFFSET 0x8 +#define VBE_DISPI_INDEX_Y_OFFSET 0x9 +#define VBE_DISPI_INDEX_NB 0xa + +#define VBE_DISPI_ID0 0xB0C0 +#define VBE_DISPI_ID1 0xB0C1 +#define VBE_DISPI_ID2 0xB0C2 + +#define VBE_DISPI_DISABLED 0x00 +#define VBE_DISPI_ENABLED 0x01 +#define VBE_DISPI_LFB_ENABLED 0x40 +#define VBE_DISPI_NOCLEARMEM 0x80 + +#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 + +#ifdef CONFIG_BOCHS_VBE + +#define VGA_STATE_COMMON_BOCHS_VBE \ + uint16_t vbe_index; \ + uint16_t vbe_regs[VBE_DISPI_INDEX_NB]; \ + uint32_t vbe_start_addr; \ + uint32_t vbe_line_offset; \ + uint32_t vbe_bank_mask; + +#else + +#define VGA_STATE_COMMON_BOCHS_VBE + +#endif /* !CONFIG_BOCHS_VBE */ + +#define CH_ATTR_SIZE (160 * 100) +#define VGA_MAX_HEIGHT 1024 + +#define VGA_STATE_COMMON \ + uint8_t *vram_ptr; \ + unsigned long vram_offset; \ + unsigned int vram_size; \ + uint32_t latch; \ + uint8_t sr_index; \ + uint8_t sr[256]; \ + uint8_t gr_index; \ + uint8_t gr[256]; \ + uint8_t ar_index; \ + uint8_t ar[21]; \ + int ar_flip_flop; \ + uint8_t cr_index; \ + uint8_t cr[256]; /* CRT registers */ \ + uint8_t msr; /* Misc Output Register */ \ + uint8_t fcr; /* Feature Control Register */ \ + uint8_t st00; /* status 0 */ \ + uint8_t st01; /* status 1 */ \ + uint8_t dac_state; \ + uint8_t dac_sub_index; \ + uint8_t dac_read_index; \ + uint8_t dac_write_index; \ + uint8_t dac_cache[3]; /* used when writing */ \ + uint8_t palette[768]; \ + int32_t bank_offset; \ + int (*get_bpp)(struct VGAState *s); \ + void (*get_offsets)(struct VGAState *s, \ + uint32_t *pline_offset, \ + uint32_t *pstart_addr); \ + void (*get_resolution)(struct VGAState *s, \ + int *pwidth, \ + int *pheight); \ + VGA_STATE_COMMON_BOCHS_VBE \ + /* display refresh support */ \ + DisplayState *ds; \ + uint32_t font_offsets[2]; \ + int graphic_mode; \ + uint8_t shift_control; \ + uint8_t double_scan; \ + uint32_t line_offset; \ + uint32_t line_compare; \ + uint32_t start_addr; \ + uint32_t plane_updated; \ + uint8_t last_cw, last_ch; \ + uint32_t last_width, last_height; /* in chars or pixels */ \ + uint32_t last_scr_width, last_scr_height; /* in pixels */ \ + uint8_t cursor_start, cursor_end; \ + uint32_t cursor_offset; \ + unsigned int (*rgb_to_pixel)(unsigned int r, \ + unsigned int g, unsigned b); \ + /* hardware mouse cursor support */ \ + uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; \ + void (*cursor_invalidate)(struct VGAState *s); \ + void (*cursor_draw_line)(struct VGAState *s, uint8_t *d, int y); \ + /* tell for each page if it has been updated since the last time */ \ + uint32_t last_palette[256]; \ + uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */ + + +typedef struct VGAState { + VGA_STATE_COMMON +} VGAState; + +static inline int c6_to_8(int v) +{ + int b; + v &= 0x3f; + b = v & 1; + return (v << 2) | (b << 1) | b; +} + +void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base, + unsigned long vga_ram_offset, int vga_ram_size); +uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr); +void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val); +void vga_invalidate_scanlines(VGAState *s, int y1, int y2); + +void vga_draw_cursor_line_8(uint8_t *d1, const uint8_t *src1, + int poffset, int w, + unsigned int color0, unsigned int color1, + unsigned int color_xor); +void vga_draw_cursor_line_16(uint8_t *d1, const uint8_t *src1, + int poffset, int w, + unsigned int color0, unsigned int color1, + unsigned int color_xor); +void vga_draw_cursor_line_32(uint8_t *d1, const uint8_t *src1, + int poffset, int w, + unsigned int color0, unsigned int color1, + unsigned int color_xor); + +extern const uint8_t sr_mask[8]; +extern const uint8_t gr_mask[16]; diff --git a/tools/ioemu/hw/vga_template.h b/tools/ioemu/hw/vga_template.h new file mode 100644 index 0000000000..909571ebb3 --- /dev/null +++ b/tools/ioemu/hw/vga_template.h @@ -0,0 +1,519 @@ +/* + * QEMU VGA Emulator templates + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if DEPTH == 8 +#define BPP 1 +#define PIXEL_TYPE uint8_t +#elif DEPTH == 15 || DEPTH == 16 +#define BPP 2 +#define PIXEL_TYPE uint16_t +#elif DEPTH == 32 +#define BPP 4 +#define PIXEL_TYPE uint32_t +#else +#error unsupport depth +#endif + +#if DEPTH != 15 + +static inline void glue(vga_draw_glyph_line_, DEPTH)(uint8_t *d, + uint32_t font_data, + uint32_t xorcol, + uint32_t bgcol) +{ +#if BPP == 1 + ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; +#elif BPP == 2 + ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol; + ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol; + ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol; +#else + ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol; +#endif +} + +static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize, + const uint8_t *font_ptr, int h, + uint32_t fgcol, uint32_t bgcol) +{ + uint32_t font_data, xorcol; + + xorcol = bgcol ^ fgcol; + do { + font_data = font_ptr[0]; + glue(vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol); + font_ptr += 4; + d += linesize; + } while (--h); +} + +static void glue(vga_draw_glyph16_, DEPTH)(uint8_t *d, int linesize, + const uint8_t *font_ptr, int h, + uint32_t fgcol, uint32_t bgcol) +{ + uint32_t font_data, xorcol; + + xorcol = bgcol ^ fgcol; + do { + font_data = font_ptr[0]; + glue(vga_draw_glyph_line_, DEPTH)(d, + expand4to8[font_data >> 4], + xorcol, bgcol); + glue(vga_draw_glyph_line_, DEPTH)(d + 8 * BPP, + expand4to8[font_data & 0x0f], + xorcol, bgcol); + font_ptr += 4; + d += linesize; + } while (--h); +} + +static void glue(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize, + const uint8_t *font_ptr, int h, + uint32_t fgcol, uint32_t bgcol, int dup9) +{ + uint32_t font_data, xorcol, v; + + xorcol = bgcol ^ fgcol; + do { + font_data = font_ptr[0]; +#if BPP == 1 + cpu_to_32wu((uint32_t *)d, (dmask16[(font_data >> 4)] & xorcol) ^ bgcol); + v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol; + cpu_to_32wu(((uint32_t *)d)+1, v); + if (dup9) + ((uint8_t *)d)[8] = v >> (24 * (1 - BIG)); + else + ((uint8_t *)d)[8] = bgcol; + +#elif BPP == 2 + cpu_to_32wu(((uint32_t *)d)+0, (dmask4[(font_data >> 6)] & xorcol) ^ bgcol); + cpu_to_32wu(((uint32_t *)d)+1, (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol); + cpu_to_32wu(((uint32_t *)d)+2, (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol); + v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol; + cpu_to_32wu(((uint32_t *)d)+3, v); + if (dup9) + ((uint16_t *)d)[8] = v >> (16 * (1 - BIG)); + else + ((uint16_t *)d)[8] = bgcol; +#else + ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol; + ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol; + v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol; + ((uint32_t *)d)[7] = v; + if (dup9) + ((uint32_t *)d)[8] = v; + else + ((uint32_t *)d)[8] = bgcol; +#endif + font_ptr += 4; + d += linesize; + } while (--h); +} + +/* + * 4 color mode + */ +static void glue(vga_draw_line2_, DEPTH)(VGAState *s1, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t plane_mask, *palette, data, v; + int x; + + palette = s1->last_palette; + plane_mask = mask16[s1->ar[0x12] & 0xf]; + width >>= 3; + for(x = 0; x < width; x++) { + data = ((uint32_t *)s)[0]; + data &= plane_mask; + v = expand2[GET_PLANE(data, 0)]; + v |= expand2[GET_PLANE(data, 2)] << 2; + ((PIXEL_TYPE *)d)[0] = palette[v >> 12]; + ((PIXEL_TYPE *)d)[1] = palette[(v >> 8) & 0xf]; + ((PIXEL_TYPE *)d)[2] = palette[(v >> 4) & 0xf]; + ((PIXEL_TYPE *)d)[3] = palette[(v >> 0) & 0xf]; + + v = expand2[GET_PLANE(data, 1)]; + v |= expand2[GET_PLANE(data, 3)] << 2; + ((PIXEL_TYPE *)d)[4] = palette[v >> 12]; + ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf]; + ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf]; + ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf]; + d += BPP * 8; + s += 4; + } +} + +#if BPP == 1 +#define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v) +#elif BPP == 2 +#define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v) +#else +#define PUT_PIXEL2(d, n, v) \ +((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v) +#endif + +/* + * 4 color mode, dup2 horizontal + */ +static void glue(vga_draw_line2d2_, DEPTH)(VGAState *s1, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t plane_mask, *palette, data, v; + int x; + + palette = s1->last_palette; + plane_mask = mask16[s1->ar[0x12] & 0xf]; + width >>= 3; + for(x = 0; x < width; x++) { + data = ((uint32_t *)s)[0]; + data &= plane_mask; + v = expand2[GET_PLANE(data, 0)]; + v |= expand2[GET_PLANE(data, 2)] << 2; + PUT_PIXEL2(d, 0, palette[v >> 12]); + PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]); + PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]); + PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]); + + v = expand2[GET_PLANE(data, 1)]; + v |= expand2[GET_PLANE(data, 3)] << 2; + PUT_PIXEL2(d, 4, palette[v >> 12]); + PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); + PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); + PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); + d += BPP * 16; + s += 4; + } +} + +/* + * 16 color mode + */ +static void glue(vga_draw_line4_, DEPTH)(VGAState *s1, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t plane_mask, data, v, *palette; + int x; + + palette = s1->last_palette; + plane_mask = mask16[s1->ar[0x12] & 0xf]; + width >>= 3; + for(x = 0; x < width; x++) { + data = ((uint32_t *)s)[0]; + data &= plane_mask; + v = expand4[GET_PLANE(data, 0)]; + v |= expand4[GET_PLANE(data, 1)] << 1; + v |= expand4[GET_PLANE(data, 2)] << 2; + v |= expand4[GET_PLANE(data, 3)] << 3; + ((PIXEL_TYPE *)d)[0] = palette[v >> 28]; + ((PIXEL_TYPE *)d)[1] = palette[(v >> 24) & 0xf]; + ((PIXEL_TYPE *)d)[2] = palette[(v >> 20) & 0xf]; + ((PIXEL_TYPE *)d)[3] = palette[(v >> 16) & 0xf]; + ((PIXEL_TYPE *)d)[4] = palette[(v >> 12) & 0xf]; + ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf]; + ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf]; + ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf]; + d += BPP * 8; + s += 4; + } +} + +/* + * 16 color mode, dup2 horizontal + */ +static void glue(vga_draw_line4d2_, DEPTH)(VGAState *s1, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t plane_mask, data, v, *palette; + int x; + + palette = s1->last_palette; + plane_mask = mask16[s1->ar[0x12] & 0xf]; + width >>= 3; + for(x = 0; x < width; x++) { + data = ((uint32_t *)s)[0]; + data &= plane_mask; + v = expand4[GET_PLANE(data, 0)]; + v |= expand4[GET_PLANE(data, 1)] << 1; + v |= expand4[GET_PLANE(data, 2)] << 2; + v |= expand4[GET_PLANE(data, 3)] << 3; + PUT_PIXEL2(d, 0, palette[v >> 28]); + PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]); + PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]); + PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]); + PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]); + PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]); + PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]); + PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]); + d += BPP * 16; + s += 4; + } +} + +/* + * 256 color mode, double pixels + * + * XXX: add plane_mask support (never used in standard VGA modes) + */ +static void glue(vga_draw_line8d2_, DEPTH)(VGAState *s1, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t *palette; + int x; + + palette = s1->last_palette; + width >>= 3; + for(x = 0; x < width; x++) { + PUT_PIXEL2(d, 0, palette[s[0]]); + PUT_PIXEL2(d, 1, palette[s[1]]); + PUT_PIXEL2(d, 2, palette[s[2]]); + PUT_PIXEL2(d, 3, palette[s[3]]); + d += BPP * 8; + s += 4; + } +} + +/* + * standard 256 color mode + * + * XXX: add plane_mask support (never used in standard VGA modes) + */ +static void glue(vga_draw_line8_, DEPTH)(VGAState *s1, uint8_t *d, + const uint8_t *s, int width) +{ + uint32_t *palette; + int x; + + palette = s1->last_palette; + width >>= 3; + for(x = 0; x < width; x++) { + ((PIXEL_TYPE *)d)[0] = palette[s[0]]; + ((PIXEL_TYPE *)d)[1] = palette[s[1]]; + ((PIXEL_TYPE *)d)[2] = palette[s[2]]; + ((PIXEL_TYPE *)d)[3] = palette[s[3]]; + ((PIXEL_TYPE *)d)[4] = palette[s[4]]; + ((PIXEL_TYPE *)d)[5] = palette[s[5]]; + ((PIXEL_TYPE *)d)[6] = palette[s[6]]; + ((PIXEL_TYPE *)d)[7] = palette[s[7]]; + d += BPP * 8; + s += 8; + } +} + +#endif /* DEPTH != 15 */ + + +/* XXX: optimize */ + +/* + * 15 bit color + */ +static void glue(vga_draw_line15_, DEPTH)(VGAState *s1, uint8_t *d, + const uint8_t *s, int width) +{ +#if DEPTH == 15 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) + memcpy(d, s, width * 2); +#else + int w; + uint32_t v, r, g, b; + + w = width; + do { + v = lduw_raw((void *)s); + r = (v >> 7) & 0xf8; + g = (v >> 2) & 0xf8; + b = (v << 3) & 0xf8; + ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); + s += 2; + d += BPP; + } while (--w != 0); +#endif +} + +/* + * 16 bit color + */ +static void glue(vga_draw_line16_, DEPTH)(VGAState *s1, uint8_t *d, + const uint8_t *s, int width) +{ +#if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) + memcpy(d, s, width * 2); +#else + int w; + uint32_t v, r, g, b; + + w = width; + do { + v = lduw_raw((void *)s); + r = (v >> 8) & 0xf8; + g = (v >> 3) & 0xfc; + b = (v << 3) & 0xf8; + ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); + s += 2; + d += BPP; + } while (--w != 0); +#endif +} + +/* + * 24 bit color + */ +static void glue(vga_draw_line24_, DEPTH)(VGAState *s1, uint8_t *d, + const uint8_t *s, int width) +{ + int w; + uint32_t r, g, b; + + w = width; + do { +#if defined(TARGET_WORDS_BIGENDIAN) + r = s[0]; + g = s[1]; + b = s[2]; +#else + b = s[0]; + g = s[1]; + r = s[2]; +#endif + ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); + s += 3; + d += BPP; + } while (--w != 0); +} + +/* + * 32 bit color + */ +static void glue(vga_draw_line32_, DEPTH)(VGAState *s1, uint8_t *d, + const uint8_t *s, int width) +{ +#if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) + memcpy(d, s, width * 4); +#else + int w; + uint32_t r, g, b; + + w = width; + do { +#if defined(TARGET_WORDS_BIGENDIAN) + r = s[1]; + g = s[2]; + b = s[3]; +#else + b = s[0]; + g = s[1]; + r = s[2]; +#endif + ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b); + s += 4; + d += BPP; + } while (--w != 0); +#endif +} + +#if DEPTH != 15 +void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1, + const uint8_t *src1, + int poffset, int w, + unsigned int color0, + unsigned int color1, + unsigned int color_xor) +{ + const uint8_t *plane0, *plane1; + int x, b0, b1; + uint8_t *d; + + d = d1; + plane0 = src1; + plane1 = src1 + poffset; + for(x = 0; x < w; x++) { + b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1; + b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1; +#if DEPTH == 8 + switch(b0 | (b1 << 1)) { + case 0: + break; + case 1: + d[0] ^= color_xor; + break; + case 2: + d[0] = color0; + break; + case 3: + d[0] = color1; + break; + } +#elif DEPTH == 16 + switch(b0 | (b1 << 1)) { + case 0: + break; + case 1: + ((uint16_t *)d)[0] ^= color_xor; + break; + case 2: + ((uint16_t *)d)[0] = color0; + break; + case 3: + ((uint16_t *)d)[0] = color1; + break; + } +#elif DEPTH == 32 + switch(b0 | (b1 << 1)) { + case 0: + break; + case 1: + ((uint32_t *)d)[0] ^= color_xor; + break; + case 2: + ((uint32_t *)d)[0] = color0; + break; + case 3: + ((uint32_t *)d)[0] = color1; + break; + } +#else +#error unsupported depth +#endif + d += BPP; + } +} +#endif + +#undef PUT_PIXEL2 +#undef DEPTH +#undef BPP +#undef PIXEL_TYPE diff --git a/tools/ioemu/i386-vl.ld b/tools/ioemu/i386-vl.ld new file mode 100644 index 0000000000..428fe83e12 --- /dev/null +++ b/tools/ioemu/i386-vl.ld @@ -0,0 +1,140 @@ +/* ld script to make i386 Linux kernel + * Written by Martin Mares ; + */ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/alpha-unknown-linux-gnu/lib); +ENTRY(_start) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0xa8000000 + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.text : + { *(.rel.text) *(.rel.gnu.linkonce.t*) } + .rela.text : + { *(.rela.text) *(.rela.gnu.linkonce.t*) } + .rel.data : + { *(.rel.data) *(.rel.gnu.linkonce.d*) } + .rela.data : + { *(.rela.data) *(.rela.gnu.linkonce.d*) } + .rel.rodata : + { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } + .rela.rodata : + { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } =0x47ff041f + .text : + { + *(.text) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } =0x47ff041f + _etext = .; + PROVIDE (etext = .); + .fini : { *(.fini) } =0x47ff041f + .rodata : { *(.rodata) *(.gnu.linkonce.r*) } + .rodata1 : { *(.rodata1) } + .reginfo : { *(.reginfo) } + __preinit_array_start = .; + .preinit_array : { *(.preinit_array) } + __preinit_array_end = .; + __init_array_start = .; + .init_array : { *(.init_array) } + __init_array_end = .; + __fini_array_start = .; + .fini_array : { *(.fini_array) } + __fini_array_end = .; + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(0x100000) + (. & (0x100000 - 1)); + .data : + { + *(.data) + *(.gnu.linkonce.d*) + CONSTRUCTORS + } + .data1 : { *(.data1) } + .ctors : + { + *(.ctors) + } + .dtors : + { + *(.dtors) + } + .plt : { *(.plt) } + .got : { *(.got.plt) *(.got) } + .dynamic : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : { *(.sdata) } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + .sbss : { *(.sbss) *(.scommon) } + .bss : + { + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* These must appear regardless of . */ +} diff --git a/tools/ioemu/i386.ld b/tools/ioemu/i386.ld new file mode 100644 index 0000000000..d41c62695e --- /dev/null +++ b/tools/ioemu/i386.ld @@ -0,0 +1,140 @@ +/* ld script to make i386 Linux kernel + * Written by Martin Mares ; + */ +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/alpha-unknown-linux-gnu/lib); +ENTRY(_start) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = 0x60000000 + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.text : + { *(.rel.text) *(.rel.gnu.linkonce.t*) } + .rela.text : + { *(.rela.text) *(.rela.gnu.linkonce.t*) } + .rel.data : + { *(.rel.data) *(.rel.gnu.linkonce.d*) } + .rela.data : + { *(.rela.data) *(.rela.gnu.linkonce.d*) } + .rel.rodata : + { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } + .rela.rodata : + { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } =0x47ff041f + .text : + { + *(.text) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + } =0x47ff041f + _etext = .; + PROVIDE (etext = .); + .fini : { *(.fini) } =0x47ff041f + . = ALIGN(32 / 8); + PROVIDE (__preinit_array_start = .); + .preinit_array : { *(.preinit_array) } + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : { *(.init_array) } + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : { *(.fini_array) } + PROVIDE (__fini_array_end = .); + .rodata : { *(.rodata) *(.gnu.linkonce.r*) } + .rodata1 : { *(.rodata1) } + .reginfo : { *(.reginfo) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(0x100000) + (. & (0x100000 - 1)); + .data : + { + *(.data) + *(.gnu.linkonce.d*) + CONSTRUCTORS + } + .data1 : { *(.data1) } + .ctors : + { + *(.ctors) + } + .dtors : + { + *(.dtors) + } + .plt : { *(.plt) } + .got : { *(.got.plt) *(.got) } + .dynamic : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : { *(.sdata) } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + .sbss : { *(.sbss) *(.scommon) } + .bss : + { + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /* These must appear regardless of . */ +} diff --git a/tools/ioemu/include/bochs.h b/tools/ioemu/include/bochs.h deleted file mode 100644 index 59b306702d..0000000000 --- a/tools/ioemu/include/bochs.h +++ /dev/null @@ -1,771 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: bochs.h,v 1.128.2.1 2004/02/06 22:14:25 danielg4 Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// -// bochs.h is the master header file for all C++ code. It includes all -// the system header files needed by bochs, and also includes all the bochs -// C++ header files. Because bochs.h and the files that it includes has -// structure and class definitions, it cannot be called from C code. -// - -#ifndef BX_BOCHS_H -# define BX_BOCHS_H 1 - -#include "config.h" /* generated by configure script from config.h.in */ - -extern "C" { - -#ifdef WIN32 -// In a win32 compile (including cygwin), windows.h is required for several -// files in gui and iodev. It is important to include it here in a header -// file so that WIN32-specific data types can be used in fields of classes. -#include -#endif - -#include -#include -#include -#include -#include - -#ifndef WIN32 -# include -#else -# include -#endif -#include -#if BX_WITH_MACOS -#define Float32 KLUDGE_Float32 -#define Float64 KLUDGE_Float64 -# include -#undef Float32 -#undef Float64 -# include -# include -# include -#elif BX_WITH_CARBON -# include -# include -# include /* for MAXPATHLEN */ -# include -#else -# ifndef WIN32 -# include -# endif -# include -# include -#endif -#include -#include -#include -#include -#ifdef macintosh -# define SuperDrive "[fd:]" -#endif -} - -#include "osdep.h" /* platform dependent includes and defines */ -#include "bxversion.h" - -#include "gui/siminterface.h" - -// prototypes -int bx_begin_simulation (int argc, char *argv[]); - -// -// some macros to interface the CPU and memory to external environment -// so that these functions can be redirected to the debugger when -// needed. -// - -#if ((BX_DEBUGGER == 1) && (BX_NUM_SIMULATORS >= 2)) -// =-=-=-=-=-=-=- Redirected to cosimulation debugger -=-=-=-=-=-=-= -#define DEV_vga_mem_read(addr) bx_dbg_ucmem_read(addr) -#define DEV_vga_mem_write(addr, val) bx_dbg_ucmem_write(addr, val) - -#if BX_SUPPORT_A20 -# define A20ADDR(x) ( (x) & bx_pc_system.a20_mask ) -#else -# define A20ADDR(x) (x) -#endif -#define BX_INP(addr, len) bx_dbg_inp(addr, len) -#define BX_OUTP(addr, val, len) bx_dbg_outp(addr, val, len) -#define BX_HRQ (bx_pc_system.HRQ) -#define BX_RAISE_HLDA() bx_dbg_raise_HLDA() -#define BX_TICK1() -#define BX_INTR bx_pc_system.INTR -#define BX_SET_INTR(b) bx_dbg_set_INTR(b) -#if BX_SIM_ID == 0 -# define BX_CPU_C bx_cpu0_c -# define BX_CPU bx_cpu0 -# define BX_MEM_C bx_mem0_c -# define BX_MEM bx_mem0 -#else -# define BX_CPU_C bx_cpu1_c -# define BX_CPU bx_cpu1 -# define BX_MEM_C bx_mem1_c -# define BX_MEM bx_mem1 -#endif -#define BX_SET_ENABLE_A20(enabled) bx_dbg_async_pin_request(BX_DBG_ASYNC_PENDING_A20, \ - enabled) -#define BX_GET_ENABLE_A20() bx_pc_system.get_enable_a20() -#error FIXME: cosim mode not fixed yet - -#else - -// =-=-=-=-=-=-=- Normal optimized use -=-=-=-=-=-=-=-=-=-=-=-=-=-= -#if BX_SUPPORT_A20 -# define A20ADDR(x) ( (x) & bx_pc_system.a20_mask ) -#else -# define A20ADDR(x) (x) -#endif -// -// some pc_systems functions just redirect to the IO devices so optimize -// by eliminating call here -// -// #define BX_INP(addr, len) bx_pc_system.inp(addr, len) -// #define BX_OUTP(addr, val, len) bx_pc_system.outp(addr, val, len) -#define BX_INP(addr, len) bx_devices.inp(addr, len) -#define BX_OUTP(addr, val, len) bx_devices.outp(addr, val, len) -#define BX_TICK1() bx_pc_system.tick1() -#define BX_TICKN(n) bx_pc_system.tickn(n) -#define BX_INTR bx_pc_system.INTR -#define BX_SET_INTR(b) bx_pc_system.set_INTR(b) -#define BX_CPU_C bx_cpu_c -#define BX_MEM_C bx_mem_c -#define BX_HRQ (bx_pc_system.HRQ) -#define BX_MEM_READ_PHYSICAL(phy_addr, len, ptr) \ - BX_MEM(0)->readPhysicalPage(BX_CPU(0), phy_addr, len, ptr) -#define BX_MEM_WRITE_PHYSICAL(phy_addr, len, ptr) \ - BX_MEM(0)->writePhysicalPage(BX_CPU(0), phy_addr, len, ptr) - -#if BX_SMP_PROCESSORS==1 -#define BX_CPU(x) (&bx_cpu) -#define BX_MEM(x) (&bx_mem) -#else -#define BX_CPU(x) (bx_cpu_array[x]) -#define BX_MEM(x) (bx_mem_array[x]) -#endif - -#define BX_SET_ENABLE_A20(enabled) bx_pc_system.set_enable_a20(enabled) -#define BX_GET_ENABLE_A20() bx_pc_system.get_enable_a20() - -#endif - - -// you can't use static member functions on the CPU, if there are going -// to be 2 cpus. Check this early on. -#if (BX_SMP_PROCESSORS>1) -# if (BX_USE_CPU_SMF!=0) -# error For SMP simulation, BX_USE_CPU_SMF must be 0. -# endif -#endif - - -// #define BX_IAC() bx_pc_system.IAC() -//#define BX_IAC() bx_dbg_IAC() - -// -// Ways for the the external environment to report back information -// to the debugger. -// - -#if BX_DEBUGGER -# define BX_DBG_ASYNC_INTR bx_guard.async.irq -# define BX_DBG_ASYNC_DMA bx_guard.async.dma -#if (BX_NUM_SIMULATORS > 1) -// for multiple simulators, we always need this info, since we're -// going to replay it. -# define BX_DBG_DMA_REPORT(addr, len, what, val) \ - bx_dbg_dma_report(addr, len, what, val) -# define BX_DBG_IAC_REPORT(vector, irq) \ - bx_dbg_iac_report(vector, irq) -# define BX_DBG_A20_REPORT(val) \ - bx_dbg_a20_report(val) -# define BX_DBG_IO_REPORT(addr, size, op, val) \ - bx_dbg_io_report(addr, size, op, val) -# define BX_DBG_UCMEM_REPORT(addr, size, op, val) -#else -// for a single simulator debug environment, we can optimize a little -// by conditionally calling, as per requested. - -# define BX_DBG_DMA_REPORT(addr, len, what, val) \ - if (bx_guard.report.dma) bx_dbg_dma_report(addr, len, what, val) -# define BX_DBG_IAC_REPORT(vector, irq) \ - if (bx_guard.report.irq) bx_dbg_iac_report(vector, irq) -# define BX_DBG_A20_REPORT(val) \ - if (bx_guard.report.a20) bx_dbg_a20_report(val) -# define BX_DBG_IO_REPORT(addr, size, op, val) \ - if (bx_guard.report.io) bx_dbg_io_report(addr, size, op, val) -# define BX_DBG_UCMEM_REPORT(addr, size, op, val) \ - if (bx_guard.report.ucmem) bx_dbg_ucmem_report(addr, size, op, val) -#endif // #if (BX_NUM_SIMULATORS > 1) - -#else // #if BX_DEBUGGER -// debugger not compiled in, use empty stubs -# define BX_DBG_ASYNC_INTR 1 -# define BX_DBG_ASYNC_DMA 1 -# define BX_DBG_DMA_REPORT(addr, len, what, val) -# define BX_DBG_IAC_REPORT(vector, irq) -# define BX_DBG_A20_REPORT(val) -# define BX_DBG_IO_REPORT(addr, size, op, val) -# define BX_DBG_UCMEM_REPORT(addr, size, op, val) -#endif // #if BX_DEBUGGER - -#define MAGIC_LOGNUM 0x12345678 - -typedef class BOCHSAPI logfunctions { - char *prefix; - int type; -// values of onoff: 0=ignore, 1=report, 2=ask, 3=fatal -#define ACT_IGNORE 0 -#define ACT_REPORT 1 -#define ACT_ASK 2 -#define ACT_FATAL 3 -#define N_ACT 4 - int onoff[N_LOGLEV]; - class iofunctions *logio; - // default log actions for all devices, declared and initialized - // in logio.cc. - BOCHSAPI_CYGONLY static int default_onoff[N_LOGLEV]; -public: - logfunctions(void); - logfunctions(class iofunctions *); - ~logfunctions(void); - - void info(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); - void error(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); - void panic(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); - void pass(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); - void ldebug(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); - void fatal (const char *prefix, const char *fmt, va_list ap, int exit_status); -#if BX_EXTERNAL_DEBUGGER - virtual void ask (int level, const char *prefix, const char *fmt, va_list ap); -#else - void ask (int level, const char *prefix, const char *fmt, va_list ap); -#endif - void put(char *); - void settype(int); - void setio(class iofunctions *); - void setonoff(int loglev, int value) { - assert (loglev >= 0 && loglev < N_LOGLEV); - onoff[loglev] = value; - } - char *getprefix () { return prefix; } - int getonoff(int level) { - assert (level>=0 && level= 0 && loglev < N_LOGLEV); - assert (action >= 0 && action < N_ACT); - default_onoff[loglev] = action; - } - static int get_default_action (int loglev) { - assert (loglev >= 0 && loglev < N_LOGLEV); - return default_onoff[loglev]; - } -} logfunc_t; - -#define BX_LOGPREFIX_SIZE 51 - -enum { - IOLOG=0, FDLOG, GENLOG, CMOSLOG, CDLOG, DMALOG, ETHLOG, G2HLOG, HDLOG, KBDLOG, - NE2KLOG, PARLOG, PCILOG, PICLOG, PITLOG, SB16LOG, SERLOG, VGALOG, - STLOG, // state_file.cc - DEVLOG, MEMLOG, DISLOG, GUILOG, IOAPICLOG, APICLOG, CPU0LOG, CPU1LOG, - CPU2LOG, CPU3LOG, CPU4LOG, CPU5LOG, CPU6LOG, CPU7LOG, CPU8LOG, CPU9LOG, - CPU10LOG, CPU11LOG, CPU12LOG, CPU13LOG, CPU14LOG, CPU15LOG, CTRLLOG, - UNMAPLOG, SERRLOG, BIOSLOG, PIT81LOG, PIT82LOG, IODEBUGLOG, PCI2ISALOG, - PLUGINLOG, EXTFPUIRQLOG , PCIVGALOG, PCIUSBLOG, VTIMERLOG, STIMERLOG -}; - -class BOCHSAPI iofunctions { - int magic; - char logprefix[BX_LOGPREFIX_SIZE]; - FILE *logfd; - class logfunctions *log; - void init(void); - void flush(void); - -// Log Class types -public: - iofunctions(void); - iofunctions(FILE *); - iofunctions(int); - iofunctions(const char *); - ~iofunctions(void); - - void out(int facility, int level, const char *pre, const char *fmt, va_list ap); - - void init_log(const char *fn); - void init_log(int fd); - void init_log(FILE *fs); - void set_log_prefix(const char *prefix); - int get_n_logfns () { return n_logfn; } - logfunc_t *get_logfn (int index) { return logfn_list[index]; } - void add_logfn (logfunc_t *fn); - void set_log_action (int loglevel, int action); - const char *getlevel(int i) { - static const char *loglevel[N_LOGLEV] = { - "DEBUG", - "INFO", - "ERROR", - "PANIC", - "PASS" - }; - if (i>=0 && i=ACT_IGNORE && idbg_xlate_linear2phy() and -// BX_CPU(n)->dword.eip, etc. -#endif - -#endif - -#if BX_DISASM -# include "disasm/disasm.h" -#endif - -typedef struct { - bx_bool floppy; - bx_bool keyboard; - bx_bool video; - bx_bool disk; - bx_bool pit; - bx_bool pic; - bx_bool bios; - bx_bool cmos; - bx_bool a20; - bx_bool interrupts; - bx_bool exceptions; - bx_bool unsupported; - bx_bool temp; - bx_bool reset; - bx_bool debugger; - bx_bool mouse; - bx_bool io; - bx_bool xms; - bx_bool v8086; - bx_bool paging; - bx_bool creg; - bx_bool dreg; - bx_bool dma; - bx_bool unsupported_io; - bx_bool serial; - bx_bool cdrom; -#ifdef MAGIC_BREAKPOINT - bx_bool magic_break_enabled; -#endif /* MAGIC_BREAKPOINT */ -#if BX_SUPPORT_APIC - bx_bool apic; - bx_bool ioapic; -#endif -#if BX_DEBUG_LINUX - bx_bool linux_syscall; -#endif - void* record_io; - } bx_debug_t; - -#define BX_ASSERT(x) do {if (!(x)) BX_PANIC(("failed assertion \"%s\" at %s:%d\n", #x, __FILE__, __LINE__));} while (0) -void bx_signal_handler (int signum); -int bx_atexit(void); -BOCHSAPI extern bx_debug_t bx_dbg; - - - -/* Already in gui/siminterface.h ??? -#define BX_FLOPPY_NONE 10 // floppy not present -#define BX_FLOPPY_1_2 11 // 1.2M 5.25" -#define BX_FLOPPY_1_44 12 // 1.44M 3.5" -#define BX_FLOPPY_2_88 13 // 2.88M 3.5" -#define BX_FLOPPY_720K 14 // 720K 3.5" -#define BX_FLOPPY_360K 15 // 360K 5.25" -#define BX_FLOPPY_LAST 15 // last one -*/ - - -#define BX_READ 0 -#define BX_WRITE 1 -#define BX_RW 2 - - - - - -#include "memory/memory.h" - - -enum PCS_OP { PCS_CLEAR, PCS_SET, PCS_TOGGLE }; - -#include "pc_system.h" -#include "plugin.h" -#include "gui/gui.h" -#include "gui/textconfig.h" -#include "gui/keymap.h" -#include "iodev/iodev.h" - - - - - - - -/* --- EXTERNS --- */ - -#if ( BX_PROVIDE_DEVICE_MODELS==1 ) -BOCHSAPI extern bx_devices_c bx_devices; -#endif - -#if BX_GUI_SIGHANDLER -extern bx_bool bx_gui_sighandler; -#endif - -// This value controls how often each I/O device's periodic() method -// gets called. The timer is set up in iodev/devices.cc. -#define BX_IODEV_HANDLER_PERIOD 100 // microseconds -//#define BX_IODEV_HANDLER_PERIOD 10 // microseconds - -char *bx_find_bochsrc (void); -int bx_parse_cmdline (int arg, int argc, char *argv[]); -int bx_read_configuration (char *rcfile); -int bx_write_configuration (char *rcfile, int overwrite); -void bx_reset_options (void); - -#define BX_PATHNAME_LEN 512 - -typedef struct { - bx_param_bool_c *Opresent; - bx_param_num_c *Oioaddr1; - bx_param_num_c *Oioaddr2; - bx_param_num_c *Oirq; - } bx_ata_options; - -typedef struct { - bx_param_string_c *Opath; - bx_param_num_c *Oaddress; - } bx_rom_options; - -typedef struct { - bx_param_string_c *Opath; - } bx_vgarom_options; - -typedef struct { - bx_param_num_c *Osize; - } bx_mem_options; - -typedef struct { - bx_param_bool_c *Oenabled; - bx_param_string_c *Ooutfile; -} bx_parport_options; - -typedef struct { - bx_param_string_c *Opath; - bx_param_bool_c *OcmosImage; - } bx_cmos_options; - -typedef struct { - bx_param_num_c *Otime0; - bx_param_enum_c *Osync; - } bx_clock_options; - -typedef struct { - bx_param_bool_c *Opresent; - bx_param_num_c *Oioaddr; - bx_param_num_c *Oirq; - bx_param_string_c *Omacaddr; - bx_param_enum_c *Oethmod; - bx_param_string_c *Oethdev; - bx_param_string_c *Oscript; - } bx_ne2k_options; - -typedef struct { -// These options are used for a special hack to load a -// 32bit OS directly into memory, so it can be run without -// any of the 16bit real mode or BIOS assistance. This -// is for the development of plex86, so we don't have -// to implement real mode up front. - bx_param_num_c *OwhichOS; - bx_param_string_c *Opath; - bx_param_string_c *Oiolog; - bx_param_string_c *Oinitrd; - } bx_load32bitOSImage_t; - -typedef struct { - bx_param_string_c *Ofilename; - bx_param_string_c *Oprefix; - bx_param_string_c *Odebugger_filename; -} bx_log_options; - -typedef struct { - bx_param_bool_c *Opresent; - bx_param_string_c *Omidifile; - bx_param_string_c *Owavefile; - bx_param_string_c *Ologfile; - bx_param_num_c *Omidimode; - bx_param_num_c *Owavemode; - bx_param_num_c *Ologlevel; - bx_param_num_c *Odmatimer; - } bx_sb16_options; - -typedef struct { - unsigned int port; - unsigned int text_base; - unsigned int data_base; - unsigned int bss_base; - } bx_gdbstub_t; - -typedef struct { - bx_param_bool_c *OuseMapping; - bx_param_string_c *Okeymap; - } bx_keyboard_options; - -#define BX_KBD_XT_TYPE 0 -#define BX_KBD_AT_TYPE 1 -#define BX_KBD_MF_TYPE 2 - -#define BX_N_OPTROM_IMAGES 4 -#define BX_N_SERIAL_PORTS 1 -#define BX_N_PARALLEL_PORTS 1 -#define BX_N_USB_HUBS 1 - -typedef struct BOCHSAPI { - bx_floppy_options floppya; - bx_floppy_options floppyb; - bx_ata_options ata[BX_MAX_ATA_CHANNEL]; - bx_atadevice_options atadevice[BX_MAX_ATA_CHANNEL][2]; - // bx_disk_options diskc; - // bx_disk_options diskd; - // bx_cdrom_options cdromd; - bx_serial_options com[BX_N_SERIAL_PORTS]; - bx_usb_options usb[BX_N_USB_HUBS]; - bx_rom_options rom; - bx_vgarom_options vgarom; - bx_rom_options optrom[BX_N_OPTROM_IMAGES]; // Optional rom images - bx_mem_options memory; - bx_parport_options par[BX_N_PARALLEL_PORTS]; // parallel ports - bx_sb16_options sb16; - bx_param_num_c *Obootdrive; - bx_param_bool_c *OfloppySigCheck; - bx_param_num_c *Ovga_update_interval; - bx_param_num_c *Okeyboard_serial_delay; - bx_param_num_c *Okeyboard_paste_delay; - bx_param_enum_c *Okeyboard_type; - bx_param_num_c *Ofloppy_command_delay; - bx_param_num_c *Oips; - bx_param_bool_c *Orealtime_pit; - bx_param_bool_c *Otext_snapshot_check; - bx_param_bool_c *Omouse_enabled; - bx_param_bool_c *Oprivate_colormap; -#if BX_WITH_AMIGAOS - bx_param_bool_c *Ofullscreen; - bx_param_string_c *Oscreenmode; -#endif - bx_param_bool_c *Oi440FXSupport; - bx_cmos_options cmos; - bx_clock_options clock; - bx_ne2k_options ne2k; - bx_param_bool_c *OnewHardDriveSupport; - bx_load32bitOSImage_t load32bitOSImage; - bx_log_options log; - bx_keyboard_options keyboard; - bx_param_string_c *Ouser_shortcut; - bx_gdbstub_t gdbstub; - bx_param_enum_c *Osel_config; - bx_param_enum_c *Osel_displaylib; - } bx_options_t; - -BOCHSAPI extern bx_options_t bx_options; - -void bx_center_print (FILE *file, char *line, int maxwidth); - -#if BX_PROVIDE_CPU_MEMORY==1 -#else -// # include "external_interface.h" -#endif - -#define BX_USE_PS2_MOUSE 1 - -int bx_init_hardware (); - -#include "instrument.h" - -// These are some convenience macros which abstract out accesses between -// a variable in native byte ordering to/from guest (x86) memory, which is -// always in little endian format. You must deal with alignment (if your -// system cares) and endian rearranging. Don't assume anything. You could -// put some platform specific asm() statements here, to make use of native -// instructions to help perform these operations more efficiently than C++. - - -#ifdef __i386__ - -#define WriteHostWordToLittleEndian(hostPtr, nativeVar16) \ - *((Bit16u*)(hostPtr)) = (nativeVar16) -#define WriteHostDWordToLittleEndian(hostPtr, nativeVar32) \ - *((Bit32u*)(hostPtr)) = (nativeVar32) -#define WriteHostQWordToLittleEndian(hostPtr, nativeVar64) \ - *((Bit64u*)(hostPtr)) = (nativeVar64) -#define ReadHostWordFromLittleEndian(hostPtr, nativeVar16) \ - (nativeVar16) = *((Bit16u*)(hostPtr)) -#define ReadHostDWordFromLittleEndian(hostPtr, nativeVar32) \ - (nativeVar32) = *((Bit32u*)(hostPtr)) -#define ReadHostQWordFromLittleEndian(hostPtr, nativeVar64) \ - (nativeVar64) = *((Bit64u*)(hostPtr)) - -#else - -#define WriteHostWordToLittleEndian(hostPtr, nativeVar16) { \ - ((Bit8u *)(hostPtr))[0] = (Bit8u) (nativeVar16); \ - ((Bit8u *)(hostPtr))[1] = (Bit8u) ((nativeVar16)>>8); \ - } -#define WriteHostDWordToLittleEndian(hostPtr, nativeVar32) { \ - ((Bit8u *)(hostPtr))[0] = (Bit8u) (nativeVar32); \ - ((Bit8u *)(hostPtr))[1] = (Bit8u) ((nativeVar32)>>8); \ - ((Bit8u *)(hostPtr))[2] = (Bit8u) ((nativeVar32)>>16); \ - ((Bit8u *)(hostPtr))[3] = (Bit8u) ((nativeVar32)>>24); \ - } -#define WriteHostQWordToLittleEndian(hostPtr, nativeVar64) { \ - ((Bit8u *)(hostPtr))[0] = (Bit8u) (nativeVar64); \ - ((Bit8u *)(hostPtr))[1] = (Bit8u) ((nativeVar64)>>8); \ - ((Bit8u *)(hostPtr))[2] = (Bit8u) ((nativeVar64)>>16); \ - ((Bit8u *)(hostPtr))[3] = (Bit8u) ((nativeVar64)>>24); \ - ((Bit8u *)(hostPtr))[4] = (Bit8u) ((nativeVar64)>>32); \ - ((Bit8u *)(hostPtr))[5] = (Bit8u) ((nativeVar64)>>40); \ - ((Bit8u *)(hostPtr))[6] = (Bit8u) ((nativeVar64)>>48); \ - ((Bit8u *)(hostPtr))[7] = (Bit8u) ((nativeVar64)>>56); \ - } -#define ReadHostWordFromLittleEndian(hostPtr, nativeVar16) { \ - (nativeVar16) = ((Bit16u) ((Bit8u *)(hostPtr))[0]) | \ - (((Bit16u) ((Bit8u *)(hostPtr))[1])<<8) ; \ - } -#define ReadHostDWordFromLittleEndian(hostPtr, nativeVar32) { \ - (nativeVar32) = ((Bit32u) ((Bit8u *)(hostPtr))[0]) | \ - (((Bit32u) ((Bit8u *)(hostPtr))[1])<<8) | \ - (((Bit32u) ((Bit8u *)(hostPtr))[2])<<16) | \ - (((Bit32u) ((Bit8u *)(hostPtr))[3])<<24); \ - } -#define ReadHostQWordFromLittleEndian(hostPtr, nativeVar64) { \ - (nativeVar64) = ((Bit64u) ((Bit8u *)(hostPtr))[0]) | \ - (((Bit64u) ((Bit8u *)(hostPtr))[1])<<8) | \ - (((Bit64u) ((Bit8u *)(hostPtr))[2])<<16) | \ - (((Bit64u) ((Bit8u *)(hostPtr))[3])<<24) | \ - (((Bit64u) ((Bit8u *)(hostPtr))[4])<<32) | \ - (((Bit64u) ((Bit8u *)(hostPtr))[5])<<40) | \ - (((Bit64u) ((Bit8u *)(hostPtr))[6])<<48) | \ - (((Bit64u) ((Bit8u *)(hostPtr))[7])<<56); \ - } - -#endif - -#ifdef BX_USE_VMX -extern int domid; -extern unsigned long megabytes; -#endif - -#endif /* BX_BOCHS_H */ diff --git a/tools/ioemu/include/bxversion.h b/tools/ioemu/include/bxversion.h deleted file mode 100644 index 1c640f9f86..0000000000 --- a/tools/ioemu/include/bxversion.h +++ /dev/null @@ -1,7 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// This file is checked in as bxversion.h.in. The configure script -// substitutes variables and creates bxversion.h. -///////////////////////////////////////////////////////////////////////// - -#define VER_STRING "2.1.1" -#define REL_STRING "February 08, 2004" diff --git a/tools/ioemu/include/config.h b/tools/ioemu/include/config.h deleted file mode 100644 index 53a72b282f..0000000000 --- a/tools/ioemu/include/config.h +++ /dev/null @@ -1,919 +0,0 @@ -/* config.h. Generated by configure. */ -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// -// config.h.in is distributed in the source TAR file. When you run -// the configure script, it generates config.h with some changes -// according to your build environment. For example, in config.h.in, -// SIZEOF_UNSIGNED_CHAR is set to 0. When configure produces config.h -// it will change "0" to the detected value for your system. -// -// config.h contains ONLY preprocessor #defines and a few typedefs. -// It must be included by both C and C++ files, so it must not -// contain anything language dependent such as a class declaration. -// - -#ifdef _BX_CONFIG_H_ -#else -#define _BX_CONFIG_H_ 1 - -/////////////////////////////////////////////////////////////////// -// USER CONFIGURABLE OPTIONS : EDIT ONLY OPTIONS IN THIS SECTION // -/////////////////////////////////////////////////////////////////// - - -#if 1 -// quit_sim is defined in gui/siminterface.h -#define BX_EXIT(x) SIM->quit_sim (x) -#else -// provide the real main and the usual exit. -#define BX_EXIT(x) ::exit(x) -#endif - -#define BX_USE_CONFIG_INTERFACE 0 -#define BX_USE_VMX 1 - -// I have tested the following combinations: -// * processors=1, bootstrap=0, ioapic_id=1 (uniprocessor system) -// * processors=2, bootstrap=0, ioapic_id=2 -// * processors=4, bootstrap=2, ioapic_id=4 -#define BX_SMP_PROCESSORS 1 -#define BX_BOOTSTRAP_PROCESSOR 0 -// choose IOAPIC id to be equal to the number of processors. This leaves -// one space for each processor to have an ID, starting with 0. -#define BX_IOAPIC_DEFAULT_ID 1 - -#define BX_ADDRESS_SPACES 1 -// controls how many instances of BX_MEM_C are created. For -// SMP, use several processors with one shared memory space. -// For cosimulation, you could use two processors and two address -// spaces. - -#define BX_SUPPORT_APIC 0 -// include in APIC models, required for a multiprocessor system. - -#if (BX_SMP_PROCESSORS>1 && !BX_SUPPORT_APIC) -#error For multiprocessor simulation, BX_SUPPORT_APIC is required. -#endif - -#define BX_DEBUG_LINUX 0 -// if simulating Linux, this provides a few more debugging options -// such as tracing all system calls. - -#define HAVE_LIBREADLINE 0 -#define HAVE_READLINE_HISTORY_H 1 -// adds support for the GNU readline library in the debugger command -// prompt. - -#define HAVE_LOCALE_H 0 -// Define to 1 if you have - -// I rebuilt the code which provides timers to IO devices. -// Setting this to 1 will introduce a little code which -// will panic out if cases which shouldn't happen occur. -// Set this to 0 for optimal performance. -#define BX_TIMER_DEBUG 1 - -// Settable A20 line. For efficiency, you can disable -// having a settable A20 line, eliminating conditional -// code for every physical memory access. You'll have -// to tell your software not to mess with the A20 line, -// and accept it as always being on if you change this. -// 1 = use settable A20 line. (normal) -// 0 = A20 is like the rest of the address lines - -#define BX_SUPPORT_A20 1 - -// Processor Instructions Per Second -// To find out what value to use for the 'ips' directive -// in your '.bochsrc' file, set BX_SHOW_IPS to 1, and -// run the software in bochs you plan to use most. Bochs -// will print out periodic IPS ratings. This will change -// based on the processor mode at the time, and various -// other factors. You'll get a reasonable estimate though. -// When you're done, reset BX_SHOW_IPS to 0, do a -// 'make all-clean', then 'make' again. - -#define BX_SHOW_IPS 0 - - -#if (BX_SHOW_IPS) && defined(__MINGW32__) -#define SIGALRM 14 -#endif - -// Paging Options: -// --------------- -// Support Paging mechanism. -// 0 = don't support paging at all (DOS & Minix don't require it) -// 1 = support paging. (Most other OS's require paging) -// Use Translation Lookaside Buffer (TLB) for caching -// paging translations. This will make paging mode -// more efficient. If you're OS doesn't use paging, -// then you won't need either. -// 1 = Use a TLB for effiency -// 0 = don't use a TLB, walk the page tables for every access -// BX_TLB_SIZE: Number of entries in TLB -// BX_TLB_INDEX_OF(lpf): This macro is passed the linear page frame -// (top 20 bits of the linear address. It must map these bits to -// one of the TLB cache slots, given the size of BX_TLB_SIZE. -// There will be a many-to-one mapping to each TLB cache slot. -// When there are collisions, the old entry is overwritten with -// one for the newest access. - -#define BX_SUPPORT_PAGING 1 -#define BX_USE_TLB 1 - -#define BX_TLB_SIZE 1024 -#define BX_TLB_INDEX_OF(lpf) (((lpf) & 0x003ff000) >> 12) - -#define BX_USE_QUICK_TLB_INVALIDATE 0 - -// Compile in support for DMA & FLOPPY IO. You'll need this -// if you plan to use the floppy drive emulation. But if -// you're environment doesn't require it, you can change -// it to 0. - -#define BX_DMA_FLOPPY_IO 1 - - -// Default number of Megs of memory to emulate. The -// 'megs:' directive in the '.bochsrc' file overrides this, -// allowing per-run settings. - -#define BX_DEFAULT_MEM_MEGS 4 - - -// CPU level emulation. Default level is set in -// the configure script. BX_CPU_LEVEL defines the CPU level -// to emulate. BX_CPU_LEVEL_HACKED is a hack to define the -// level of some integer instructions, so they can be tested -// before the rest of the emulation is up to that level. - -#define BX_CPU_LEVEL 5 -#define BX_CPU_LEVEL_HACKED 5 - -// emulate x86-64 instruction set? -#define BX_SUPPORT_X86_64 0 - -// Virtual 8086 mode emulation. -// 1 = compile in support for v8086 mode. -// 0 = don't compile in support for v8086 mode. -#define BX_SUPPORT_V8086_MODE 1 - -// Defines if the simulation should reset on triple fault -// if set to 0, the simulation will panic. -#define BX_RESET_ON_TRIPLE_FAULT 1 - -// Support shadowing of ROM from C0000 to FFFFF. -// This allows that region to be written to. -#define BX_SHADOW_RAM 0 - -// Number of CMOS registers -#define BX_NUM_CMOS_REGS 64 -//#define BX_NUM_CMOS_REGS 128 - -// Use Greg Alexander's new PIT model (summer 2001) instead of the original. -#define BX_USE_NEW_PIT 1 - -#define BX_USE_SLOWDOWN_TIMER 0 -#define BX_HAVE_SLEEP 1 -#define BX_HAVE_MSLEEP 0 -#define BX_HAVE_USLEEP 1 -#define BX_HAVE_NANOSLEEP 1 -#define BX_HAVE_ABORT 1 -#define BX_HAVE_SOCKLEN_T 1 -#define BX_HAVE_SOCKADDR_IN_SIN_LEN 0 -#define BX_HAVE_GETTIMEOFDAY 1 -#if defined(WIN32) -#define BX_HAVE_REALTIME_USEC 1 -#else -#define BX_HAVE_REALTIME_USEC (BX_HAVE_GETTIMEOFDAY) -#endif -#define BX_HAVE_MKSTEMP 1 -#define BX_HAVE_SYS_MMAN_H 1 -#define BX_HAVE_XPM_H 1 -#define BX_HAVE_TIMELOCAL 1 -#define BX_HAVE_GMTIME 1 -#define BX_HAVE_MKTIME 1 - -// This turns on Roland Mainz's idle hack. Presently it is specific to the X11 -// gui. If people try to enable it elsewhere, give a compile error after the -// gui definition so that they don't waste their time trying. -#define BX_USE_IDLE_HACK 0 - -// Minimum Emulated IPS. -// This is used in the realtime PIT as well as for checking the -// IPS value set in the config file. -#define BX_MIN_IPS 200000 - -// Use Static Member Funtions to eliminate 'this' pointer passing -// If you want the efficiency of 'C', you can make all the -// members of the C++ CPU class to be static. -// This defaults to 1 since it should improve performance, but when -// SMP mode is enabled, it will be turned off by configure. - -#define BX_USE_CPU_SMF 1 - -// Use static member functions in IO DEVice emulation modules. -// For efficiency, use C like functions for IO handling, -// and declare a device instance at compile time, -// instead of using 'new' and storing the pointer. This -// eliminates some overhead, especially for high-use IO -// devices like the disk drive. -// 1 = Use static member efficiency (normal) -// 0 = Use nonstatic member functions (use only if you need -// multiple instances of a device class - -#define BX_USE_HD_SMF 1 // Hard drive -#define BX_USE_BIOS_SMF 1 // BIOS -#define BX_USE_CMOS_SMF 1 // CMOS -#define BX_USE_DMA_SMF 1 // DMA -#define BX_USE_FD_SMF 1 // Floppy -#define BX_USE_KEY_SMF 1 // Keyboard -#define BX_USE_PAR_SMF 1 // Parallel -#define BX_USE_PIC_SMF 1 // PIC -#define BX_USE_PIT_SMF 1 // PIT -#define BX_USE_SER_SMF 1 // Serial -#define BX_USE_UM_SMF 1 // Unmapped -#define BX_USE_VGA_SMF 1 // VGA -#define BX_USE_SB16_SMF 1 // Sound (SB 16) -#define BX_USE_DEV_SMF 1 // System Devices (port92) -#define BX_USE_PCI_SMF 1 // PCI -#define BX_USE_P2I_SMF 1 // PCI-to-ISA bridge -#define BX_USE_PCIVGA_SMF 1 // PCI-VGA -#define BX_USE_PCIUSB_SMF 1 // USB hub -#define BX_USE_NE2K_SMF 1 // NE2K -#define BX_USE_EFI_SMF 1 // External FPU IRQ -#define BX_USE_GAME_SMF 1 // Gameport - -#define BX_PLUGINS 0 -#define BX_HAVE_DLFCN_H 1 - -#if BX_PLUGINS && \ - ( !BX_USE_HD_SMF || !BX_USE_BIOS_SMF || !BX_USE_CMOS_SMF \ - || !BX_USE_DMA_SMF || !BX_USE_FD_SMF || !BX_USE_KEY_SMF \ - || !BX_USE_PAR_SMF || !BX_USE_PIC_SMF || !BX_USE_PIT_SMF \ - || !BX_USE_SER_SMF || !BX_USE_UM_SMF || !BX_USE_VGA_SMF \ - || !BX_USE_SB16_SMF || !BX_USE_DEV_SMF || !BX_USE_PCI_SMF \ - || !BX_USE_P2I_SMF || !BX_USE_PCIVGA_SMF || !BX_USE_PCIUSB_SMF \ - || !BX_USE_NE2K_SMF || !BX_USE_EFI_SMF || !BX_USE_GAME_SMF) -#error You must use SMF to have plugins -#endif - -#define BX_SUPPORT_SB16 0 -#define BX_SUPPORT_GAME 0 - -#if BX_SUPPORT_SB16 -// Use virtual methods for the sound output functions -#define BX_USE_SOUND_VIRTUAL 1 -// Determines which sound output class is to be used. -// Currently the following are available: -// bx_sound_linux_c Output for Linux, to /dev/dsp and /dev/midi00 -// bx_sound_windows_c Output for Windows midi and wave mappers -// bx_sound_output_c Dummy functions, no output -#define BX_SOUND_OUTPUT_C bx_sound_output_c -#endif - -#define USE_RAW_SERIAL 0 - -#define BX_USE_SPECIFIED_TIME0 0 - -// This enables writing to port 0xe9 and the output -// is sent to the console. Reading from port 0xe9 -// will return 0xe9 to let you know this is available. -// Leave this 0 unless you have a reason to use it. -#define BX_PORT_E9_HACK 1 - -#define BX_GDBSTUB 0 - -// This option enables compressed (zlib) hd support -#define BX_COMPRESSED_HD_SUPPORT 0 -#define BX_HAVE_ZLIB 1 - -#if BX_COMPRESSED_HD_SUPPORT && !BX_HAVE_ZLIB -#error You must have zlib to enable compressed hd support -#endif - -// This option defines the number of supported ATA channels. -// There are up to two drives per ATA channel. -#define BX_MAX_ATA_CHANNEL 4 - -#if (BX_MAX_ATA_CHANNEL>4 || BX_MAX_ATA_CHANNEL<1) -# error "BX_MAX_ATA_CHANNEL should be between 1 and 4" -#endif - -// ================================================================= -// BEGIN: OPTIONAL DEBUGGER SECTION -// -// These options are only used if you compile in support for the -// native command line debugging environment. Typically, the debugger -// is not used, and this section can be ignored. -// ================================================================= - -#define BX_MAX_DIRTY_PAGE_TABLE_MEGS 1024 - -// Compile in support for virtual/linear/physical breakpoints. -// Set to 1, only those you need. Recommend using only linear -// breakpoints, unless you need others. Less supported means -// slightly faster execution time. -#define BX_DBG_SUPPORT_VIR_BPOINT 1 -#define BX_DBG_SUPPORT_LIN_BPOINT 1 -#define BX_DBG_SUPPORT_PHY_BPOINT 1 - -// You need only define one initial breakpoint into each -// cpu simulator (emulator) here. Each simulator sets callbacks -// and variables which the debugger uses from then on. -#define BX_SIM1_INIT bx_dbg_init_cpu_mem_env0 -#ifndef BX_SIM2_INIT -#define BX_SIM2_INIT bx_dbg_init_cpu_mem_env1 -#endif -//#define BX_SIM2_INIT sim2_init - -// max number of virtual/linear/physical breakpoints handled -#define BX_DBG_MAX_VIR_BPOINTS 10 -#define BX_DBG_MAX_LIN_BPOINTS 10 -#define BX_DBG_MAX_PHY_BPOINTS 10 - -// max file pathname size for debugger commands -#define BX_MAX_PATH 256 -// max nesting level for debug scripts including other scripts -#define BX_INFILE_DEPTH 10 -// use this command to include (nest) debug scripts -#define BX_INCLUDE_CMD "source" - -// Use either 32 or 64 bit instruction counter for -// debugger purposes. Uncomment one of these. -//#define BX_DBG_ICOUNT_SIZE 32 -#define BX_DBG_ICOUNT_SIZE 64 - -// Make a call to command line debugger extensions. If set to 1, -// a call is made. An external routine has a chance to process -// the command. If it does, than the debugger ignores the command. -#define BX_DBG_EXTENSIONS 0 - -// ================================================================= -// END: OPTIONAL DEBUGGER SECTION -// ================================================================= - - -////////////////////////////////////////////////////////////////////// -// END OF USER CONFIGURABLE OPTIONS : DON'T EDIT ANYTHING BELOW !!! // -// THIS IS GENERATED BY THE ./configure SCRIPT // -////////////////////////////////////////////////////////////////////// - - -#define BX_WITH_X11 1 -#define BX_WITH_BEOS 0 -#define BX_WITH_WIN32 0 -#define BX_WITH_MACOS 0 -#define BX_WITH_CARBON 0 -#define BX_WITH_NOGUI 0 -#define BX_WITH_TERM 1 -#define BX_WITH_RFB 1 -#define BX_WITH_AMIGAOS 0 -#define BX_WITH_SDL 0 -#define BX_WITH_SVGA 0 -#define BX_WITH_WX 0 - -// add special export symbols for win32 DLL building. The main code must -// have __declspec(dllexport) on variables, functions, or classes that the -// plugins can access. The plugins should #define PLUGGABLE which will -// activate the __declspec(dllimport) instead. -#if defined(WIN32) || defined(__CYGWIN__) -# if BX_PLUGINS && defined(BX_PLUGGABLE) -// #warning I will import DLL symbols from Bochs main program. -# define BOCHSAPI __declspec(dllimport) -# else -// #warning I will export DLL symbols. -# define BOCHSAPI __declspec(dllexport) -# endif -#endif -#ifndef BOCHSAPI -# define BOCHSAPI -#endif - -#if defined(__CYGWIN__) -// Make BOCHSAPI_CYGONLY exactly the same as BOCHSAPI. This symbol -// will be used for any cases where Cygwin requires a special tag -// but VC++ does not. -#define BOCHSAPI_CYGONLY BOCHSAPI -#else -// define the symbol to be empty -#define BOCHSAPI_CYGONLY /*empty*/ -#endif - -#define BX_DEFAULT_CONFIG_INTERFACE "defined_by_configure" -#define BX_DEFAULT_DISPLAY_LIBRARY "defined_by_configure" - -// Roland Mainz's idle hack is presently specific to X11. If people try to -// enable it elsewhere, give a compile error so that they don't waste their -// time trying. -#if (BX_USE_IDLE_HACK && !BX_WITH_X11) -# error IDLE_HACK will only work with the X11 gui. Correct configure args and retry. -#endif - -#define WORDS_BIGENDIAN 0 - -#define SIZEOF_UNSIGNED_CHAR 1 -#define SIZEOF_UNSIGNED_SHORT 2 -#define SIZEOF_UNSIGNED_INT 4 -#define SIZEOF_UNSIGNED_LONG 4 -#define SIZEOF_UNSIGNED_LONG_LONG 8 -#define SIZEOF_INT_P 4 - -#define BX_64BIT_CONSTANTS_USE_LL 1 -#if BX_64BIT_CONSTANTS_USE_LL -// doesn't work on Microsoft Visual C++, maybe others -#define BX_CONST64(x) (x##LL) -#else -#define BX_CONST64(x) (x) -#endif - -#if defined(WIN32) - typedef unsigned char Bit8u; - typedef signed char Bit8s; - typedef unsigned short Bit16u; - typedef signed short Bit16s; - typedef unsigned int Bit32u; - typedef signed int Bit32s; -#ifdef __MINGW32__ - typedef unsigned long long Bit64u; - typedef signed long long Bit64s; -#include -#else - typedef unsigned __int64 Bit64u; - typedef signed __int64 Bit64s; -#endif -#elif BX_WITH_MACOS - typedef unsigned char Bit8u; - typedef signed char Bit8s; - typedef unsigned short Bit16u; - typedef signed short Bit16s; - typedef unsigned int Bit32u; - typedef signed int Bit32s; - typedef unsigned long long Bit64u; - typedef signed long long Bit64s; -#else - -// Unix like platforms - -#if SIZEOF_UNSIGNED_CHAR != 1 -# error "sizeof (unsigned char) != 1" -#else - typedef unsigned char Bit8u; - typedef signed char Bit8s; -#endif - -#if SIZEOF_UNSIGNED_SHORT != 2 -# error "sizeof (unsigned short) != 2" -#else - typedef unsigned short Bit16u; - typedef signed short Bit16s; -#endif - -#if SIZEOF_UNSIGNED_INT == 4 - typedef unsigned int Bit32u; - typedef signed int Bit32s; -#elif SIZEOF_UNSIGNED_LONG == 4 - typedef unsigned long Bit32u; - typedef signed long Bit32s; -#else -# error "can't find sizeof(type) of 4 bytes!" -#endif - -#if SIZEOF_UNSIGNED_LONG == 8 - typedef unsigned long Bit64u; - typedef signed long Bit64s; -#elif SIZEOF_UNSIGNED_LONG_LONG == 8 - typedef unsigned long long Bit64u; - typedef signed long long Bit64s; -#else -# error "can't find data type of 8 bytes" -#endif - -#endif - -// now that Bit32u and Bit64u exist, defined bx_address -#if BX_SUPPORT_X86_64 -typedef Bit64u bx_address; -#else -typedef Bit32u bx_address; -#endif - - -// technically, in an 8 bit signed the real minimum is -128, not -127. -// But if you decide to negate -128 you tend to get -128 again, so it's -// better not to use the absolute maximum in the signed range. -#define BX_MAX_BIT64U ( (Bit64u) -1 ) -#define BX_MIN_BIT64U ( 0 ) -#define BX_MAX_BIT64S ( ((Bit64u) -1) >> 1 ) -#define BX_MIN_BIT64S ( -(((Bit64u) -1) >> 1) ) -#define BX_MAX_BIT32U ( (Bit32u) -1 ) -#define BX_MIN_BIT32U ( 0 ) -#define BX_MAX_BIT32S ( ((Bit32u) -1) >> 1 ) -#define BX_MIN_BIT32S ( -(((Bit32u) -1) >> 1) ) -#define BX_MAX_BIT16U ( (Bit16u) -1 ) -#define BX_MIN_BIT16U ( 0 ) -#define BX_MAX_BIT16S ( ((Bit16u) -1) >> 1 ) -#define BX_MIN_BIT16S ( -(((Bit16u) -1) >> 1) ) -#define BX_MAX_BIT8U ( (Bit8u) -1 ) -#define BX_MIN_BIT8U ( 0 ) -#define BX_MAX_BIT8S ( ((Bit8u) -1) >> 1 ) -#define BX_MIN_BIT8S ( -(((Bit8u) -1) >> 1) ) - - -// create an unsigned integer type that is the same size as a pointer. -// You can typecast a pointer to a bx_pr_equiv_t without losing any -// bits (and without getting the compiler excited). This is used in -// the FPU emulation code, where pointers and integers are often -// used interchangeably. -#if SIZEOF_INT_P == 4 - typedef Bit32u bx_ptr_equiv_t; -#elif SIZEOF_INT_P == 8 - typedef Bit64u bx_ptr_equiv_t; -#else -# error "could not define bx_ptr_equiv_t to size of int*" -#endif - -// Use a boolean type that will not conflict with the builtin type -// on any system. -typedef Bit32u bx_bool; - -#if BX_WITH_MACOS -# define bx_ptr_t char * -#else -# define bx_ptr_t void * -#endif - -#if defined(WIN32) -# define BX_LITTLE_ENDIAN -#elif BX_WITH_MACOS -# define BX_BIG_ENDIAN -#else -#if WORDS_BIGENDIAN -# define BX_BIG_ENDIAN -#else -# define BX_LITTLE_ENDIAN -#endif -#endif // defined(WIN32) - - -#if BX_SUPPORT_X86_64 -#ifdef BX_LITTLE_ENDIAN -typedef - struct { - Bit64u lo; - Bit64u hi; - } Bit128u; -typedef - struct { - Bit64u lo; - Bit64s hi; - } Bit128s; -#else // must be Big Endian -typedef - struct { - Bit64u hi; - Bit64u lo; - } Bit128u; -typedef - struct { - Bit64s hi; - Bit64u lo; - } Bit128s; -#endif -#endif // #if BX_SUPPORT_X86_64 - - -// for now only term.cc requires a GUI sighandler. -#define BX_GUI_SIGHANDLER (BX_WITH_TERM) - -#define HAVE_SIGACTION 1 - -// configure will change the definition of "inline" to the value -// that the C compiler allows. It tests the following keywords to -// see if any is permitted: inline, __inline__, __inline. If none -// is permitted, it defines inline to be empty. -#define inline inline - -// inline functions in headers that are compiled with C compiler -// (e.g. fpu code) are declared with BX_C_INLINE macro. Note that -// the word "inline" itself may now be redefined by the above #define. -// Many compilers are known to work with "static inline". If the -// compiler can put the function inline, it does so and never creates -// a symbol for the function. If optimization is off, or inline is -// defined to be empty, the static keyword causes the function to create -// a symbol that's visible only to that .c file. Each .c file that -// includes the header will produde another local version of the -// BX_C_INLINE function (not ideal). However without "static" you can -// duplicate symbol problems which are even worse. -#define BX_C_INLINE static inline - -// Use BX_CPP_INLINE for all C++ inline functions. Note that the -// word "inline" itself may now be redefined by the above #define. -#define BX_CPP_INLINE inline - -#ifdef __GNUC__ - -// Some helpful compiler hints for compilers that allow them; GCC for now. -// -// BX_CPP_AlignN(n): -// Align a construct on an n-byte boundary. -// -// BX_CPP_AttrPrintf(formatArg, firstArg): -// This function takes printf-like arguments, so the compiler can check -// the consistency of the format string and the matching arguments. -// 'formatArg' is the parameter number (starting from 1) of the format -// string argument. 'firstArg' is the parameter number of the 1st argument -// to check against the string argument. NOTE: For non-static member -// functions, the this-ptr is argument number 1 but is invisible on -// the function prototype declaration - but you still have to count it. -// -// BX_CPP_AttrNoReturn(): -// This function never returns. The compiler can optimize-out following -// code accordingly. - -#define BX_CPP_AlignN(n) __attribute__ ((aligned (n))) -#define BX_CPP_AttrPrintf(formatArg, firstArg) \ - __attribute__ ((format (printf, formatArg, firstArg))) -#define BX_CPP_AttrNoReturn() __attribute__ ((noreturn)) - -#else - -#define BX_CPP_AlignN(n) /* Not supported. */ -#define BX_CPP_AttrPrintf(formatArg, firstArg) /* Not supported. */ -#define BX_CPP_AttrNoReturn() /* Not supported. */ - -#endif - -#define BX_DEBUGGER 0 -#define BX_DISASM 0 - -#define BX_PROVIDE_CPU_MEMORY 1 -#define BX_PROVIDE_DEVICE_MODELS 1 - -#define BX_SUPPORT_VBE 0 - -#define BX_PROVIDE_MAIN 1 - -#define BX_INSTRUMENTATION 0 - -#define BX_USE_LOADER 0 - -// for debugger, CPU simulator handle ID -// 0 is the default, for using only one CPU simulator -// 1 is for the 2nd CPU simulator -#define BX_SIM_ID 0 -#define BX_NUM_SIMULATORS 1 - -// limited i440FX PCI support -#define BX_PCI_SUPPORT 1 - -// Experimental VGA on PCI -#define BX_PCI_VGA_SUPPORT 1 - -// limited USB on PCI -#define BX_PCI_USB_SUPPORT 1 - -#if (BX_PCI_USB_SUPPORT && !BX_PCI_SUPPORT) -#error To enable USB, you must also enable PCI -#endif - -// Promise VLBIDE DC2300 Support -#define BX_PDC20230C_VLBIDE_SUPPORT 0 - -#define BX_SUPPORT_FPU 1 -#define BX_SUPPORT_MMX 1 -#define BX_SUPPORT_3DNOW 0 -#define BX_SUPPORT_SSE 0 -#define BX_SUPPORT_DAZ 0 -#define BX_SUPPORT_PNI 0 -#define BX_SUPPORT_SEP 0 -#define BX_SUPPORT_4MEG_PAGES 0 - -#define BX_SupportGuest2HostTLB 0 -#define BX_SupportRepeatSpeedups 0 -#define BX_SupportGlobalPages 0 -#define BX_SupportPAE 0 -#define BX_SupportICache 0 -#define BX_SupportHostAsms 1 - - -// if 1, don't do gpf on MSRs that we don't implement -#define BX_IGNORE_BAD_MSR 0 - -// ======================================================== -// These are some very temporary hacks I made to the 64-bit -// support to help Peter with debugging etc. They will be removed -// soon and there is no configure option for them (on purpose). -// By default, they are not compiled in. - -// I set this to 1 to bail in instructions which may not be honoring -// the 64-bit widths of RIP/RSP. If I trip a panic, then I clean -// the function up and remove the panic. You don't have to use -// these. -#if 0 -#define BailBigRSP(s) \ - if ( (RIP > 0xffffffff) || \ - (RSP > 0xffffffff) ) \ - BX_PANIC((s ": bailing due to big RSP value, mode==%u", \ - BX_CPU_THIS_PTR cpu_mode)) -#else -#define BailBigRSP(s) -#endif -// ======================================================== - - -#if (BX_SUPPORT_MMX && BX_CPU_LEVEL < 5) -#error With CPU level < 5, you must disable MMX support. -#endif - -#if (!BX_SUPPORT_FPU && BX_CPU_LEVEL >= 5) -#error With CPU level >= 5, you must enable FPU support. -#endif - -#if (BX_SUPPORT_MMX && !BX_SUPPORT_FPU) -#error "MMX cannot be compiled without FPU support" -#endif - -#if (BX_SUPPORT_3DNOW && !BX_SUPPORT_MMX) -#error "3DNow! cannot be compiled without MMX support" -#endif - -#if (BX_SUPPORT_SSE && !BX_SUPPORT_MMX) -#error "SSE cannot be compiled without FPU+MMX support" -#endif - -#if (BX_CPU_LEVEL<6 && BX_SUPPORT_SSE) -#error SSE is only supported with CPU_LEVEL >= 6 -#endif - -#if (BX_SUPPORT_PNI && BX_SUPPORT_SSE <= 1) -#error "PNI cannot be compiled without SSE/SSE2 support" -#endif - -#if (BX_CPU_LEVEL<6 && BX_SUPPORT_SEP) -#error SYSENTER/SYSEXIT only supported with CPU_LEVEL >= 6 -#endif - -#if BX_SUPPORT_X86_64 -// Sanity checks to ensure that you cannot accidently use conflicting options. - -#if BX_CPU_LEVEL < 5 -#error X86-64 requires cpu level 6 or greater -#endif -#if (BX_SUPPORT_SSE<2) -#error X86-64 requires SSE2 -#endif -#if !BX_SupportPAE -#error X86-64 requires Physical Address Extensions (PAE) -#endif -#if !BX_SupportGlobalPages -#error X86-64 requires Page Global Extension (PGE) -#endif -#if !BX_SUPPORT_4MEG_PAGES -#error X86-64 requires Page Size Extension (PSE) -#endif - -#if BX_SUPPORT_SEP -#error SYSENTER/SYSEXIT not implemented for X86-64 -#endif - -#endif - -#define BX_HAVE_GETENV 1 -#define BX_HAVE_SETENV 1 -#define BX_HAVE_SELECT 1 -#define BX_HAVE_SNPRINTF 1 -#define BX_HAVE_STRTOULL 1 -#define BX_HAVE_STRTOUQ 1 -#define BX_HAVE_STRDUP 1 -#define BX_HAVE_STRREV 0 -#define BX_HAVE_STRUCT_TIMEVAL 1 - -// used in term gui -#define BX_HAVE_COLOR_SET 0 -#define BX_HAVE_MVHLINE 0 -#define BX_HAVE_MVVLINE 0 - - -// set if your compiler does not permit an empty struct -#define BX_NO_EMPTY_STRUCTS 0 - -// set if your compiler does not understand __attribute__ after a struct -#define BX_NO_ATTRIBUTES 0 -#if BX_NO_ATTRIBUTES -#define GCC_ATTRIBUTE(x) /* attribute not supported */ -#else -#define GCC_ATTRIBUTE __attribute__ -#endif - -// set to use fast function calls -#define BX_FAST_FUNC_CALL 0 - -// On gcc2.95+ x86 only -#if BX_FAST_FUNC_CALL && defined(__i386__) && defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)) -# define BX_CPP_AttrRegparmN(X) __attribute__((regparm(X))) -#else -# define BX_CPP_AttrRegparmN(X) /* Not defined */ -#endif - -// set if your compiler does not allow label at the end of a {} block -#define BX_NO_BLANK_LABELS 0 - -// set if you do have , used in bx_debug/dbg_main.c -#define BX_HAVE_HASH_MAP 0 - -// set if you do have , used in bx_debug/dbg_main.c -#define BX_HAVE_HASH_MAP_H 1 - -// set if you do have , used in bx_debug/dbg_main.c -#define BX_HAVE_SET 1 - -// set if you do have , used in bx_debug/dbg_main.c -#define BX_HAVE_SET_H 1 - -// Support x86 hardware debugger registers and facilites. -// These are the debug facilites offered by the x86 architecture, -// not the optional built-in debugger. -#define BX_X86_DEBUGGER 0 - -#define BX_SUPPORT_CDROM 1 - -#if BX_SUPPORT_CDROM - // This is the C++ class name to use if we are supporting - // low-level CDROM. -# define LOWLEVEL_CDROM cdrom_interface -#endif - -// NE2K network emulation -#define BX_NE2K_SUPPORT 1 -#define BX_ETH_NULL_LOGGING 1 -#define BX_ETH_FBSD_LOGGING 1 - -// determine which NE2K packet mover modules will be enabled -// (this was moved from iodev/eth.h) -#define ETH_NULL 1 -#ifdef BX_USE_ETH_ARPBACK -# define ETH_ARPBACK 1 -#endif -#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) -#define ETH_FBSD 1 -#endif -#if defined(linux) -#define ETH_LINUX 1 -#endif -#if defined(WIN32) -#define ETH_WIN32 1 -#endif - -// this enables Ethertap packet mover; determined by configure script -#define HAVE_ETHERTAP 0 - -// this enables TUN/TAP packet mover; determined by configure script -#define HAVE_TUNTAP 1 - - -// I/O Interface to debug -#define BX_IODEBUG_SUPPORT 0 - -// External Debugger -#define BX_EXTERNAL_DEBUGGER 0 -#define BX_OVERRIDE_ASK 0 - -#ifdef WIN32 -#define BX_FLOPPY0_NAME "Floppy Disk A:" -#define BX_FLOPPY1_NAME "Floppy Disk B:" -#else -#define BX_FLOPPY0_NAME "Floppy Disk 0" -#define BX_FLOPPY1_NAME "Floppy Disk 1" -#endif - -// This is handy for certain performance testing purposes, but otherwise -// totally useless. If you define BX_SCHEDULED_DIE_TIME then it enables code -// in bx_pit_c::periodic that will cause Bochs to exit() after a certain number -// of instructions. -//#define BX_SCHEDULED_DIE_TIME 1162230000 // end of redhat6.0 boot - - -#endif // _BX_CONFIG_H diff --git a/tools/ioemu/include/cpu/cpu.h b/tools/ioemu/include/cpu/cpu.h deleted file mode 100644 index 0627ee385e..0000000000 --- a/tools/ioemu/include/cpu/cpu.h +++ /dev/null @@ -1,116 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: cpu.h,v 1.155 2003/12/30 22:12:45 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -#ifndef BX_CPU_H -# define BX_CPU_H 1 - -#include -#ifdef BX_USE_VMX -extern "C" { -#include -} -#endif - - -#if BX_SUPPORT_APIC -#define BX_CPU_INTR (BX_CPU_THIS_PTR INTR || BX_CPU_THIS_PTR local_apic.INTR) -#else -#define BX_CPU_INTR BX_CPU_THIS_PTR INTR -#endif - -class BX_CPU_C; -class BX_MEM_C; - -#if BX_USE_CPU_SMF == 0 -// normal member functions. This can ONLY be used within BX_CPU_C classes. -// Anyone on the outside should use the BX_CPU macro (defined in bochs.h) -// instead. -# define BX_CPU_THIS_PTR this-> -# define BX_CPU_THIS this -# define BX_SMF -# define BX_CPU_C_PREFIX BX_CPU_C:: -// with normal member functions, calling a member fn pointer looks like -// object->*(fnptr)(arg, ...); -// Since this is different from when SMF=1, encapsulate it in a macro. -# define BX_CPU_CALL_METHOD(func, args) \ - (this->*((BxExecutePtr_t) (func))) args -# define BX_CPU_CALL_METHODR(func, args) \ - (this->*((BxExecutePtr_tR) (func))) args -#else -// static member functions. With SMF, there is only one CPU by definition. -# define BX_CPU_THIS_PTR BX_CPU(0)-> -# define BX_CPU_THIS BX_CPU(0) -# define BX_SMF static -# define BX_CPU_C_PREFIX -# define BX_CPU_CALL_METHOD(func, args) \ - ((BxExecutePtr_t) (func)) args -# define BX_CPU_CALL_METHODR(func, args) \ - ((BxExecutePtr_tR) (func)) args -#endif - -#if BX_SMP_PROCESSORS==1 -// single processor simulation, so there's one of everything -BOCHSAPI extern BX_CPU_C bx_cpu; -#else -// multiprocessor simulation, we need an array of cpus and memories -BOCHSAPI extern BX_CPU_C *bx_cpu_array[BX_SMP_PROCESSORS]; -#endif - -class BOCHSAPI BX_CPU_C : public logfunctions { - -public: // for now... - - volatile bx_bool async_event; - volatile bx_bool INTR; - volatile bx_bool kill_bochs_request; - - // constructors & destructors... - BX_CPU_C(); - ~BX_CPU_C(void); - void init (BX_MEM_C *addrspace); - void interrupt(Bit8u vector); - - BX_SMF void pagingA20Changed(void); - BX_SMF void reset(unsigned source); - BX_SMF void set_INTR(bx_bool value); - BX_SMF void atexit(void); - - // now for some ancillary functions... - void cpu_loop(Bit32s max_instr_count); - -#ifdef BX_USE_VMX - ioreq_t* __get_ioreq(void); - ioreq_t* get_ioreq(void); - void dispatch_ioreq(ioreq_t *req); - void handle_ioreq(); - void timer_handler(); - - int send_event; -#endif -}; - -#endif // #ifndef BX_CPU_H diff --git a/tools/ioemu/include/extplugin.h b/tools/ioemu/include/extplugin.h deleted file mode 100644 index f3e43f79d4..0000000000 --- a/tools/ioemu/include/extplugin.h +++ /dev/null @@ -1,51 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: extplugin.h,v 1.4 2002/12/12 15:28:37 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// extplugin.h -// -// This header file defines the types necessary to make a Bochs plugin, -// but without mentioning all the details of Bochs internals (bochs.h). -// It is included by the configuration interfaces and possibly other -// things which are intentionally isolated from other parts of the program. -// -// The plugin_t struct comes from the plugin.h file from plex86. -// Plex86 is Copyright (C) 1999-2000 The plex86 developers team -// -///////////////////////////////////////////////////////////////////////// - -#ifndef __EXTPLUGIN_H -#define __EXTPLUGIN_H - -#if BX_PLUGINS -#include "ltdl.h" -#endif - -enum plugintype_t { - PLUGTYPE_NULL=100, - PLUGTYPE_CORE, - PLUGTYPE_OPTIONAL, - PLUGTYPE_USER -}; - -#define MAX_ARGC 10 - -typedef struct _plugin_t -{ - plugintype_t type; - int initialized; -#if BX_PLUGINS - lt_dlhandle handle; -#endif - int argc; - char *name, *args, *argv[MAX_ARGC]; - int (*plugin_init)(struct _plugin_t *plugin, plugintype_t type, int argc, char *argv[]); - void (*plugin_fini)(void); - - struct _plugin_t *next; -} plugin_t; - - - -#endif /* __EXTPLUGIN_H */ - diff --git a/tools/ioemu/include/instrument.h b/tools/ioemu/include/instrument.h deleted file mode 100644 index 8d753ff7d7..0000000000 --- a/tools/ioemu/include/instrument.h +++ /dev/null @@ -1,256 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: instrument.h,v 1.14 2003/10/09 19:05:13 sshwarts Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -// possible types passed to BX_INSTR_TLB_CNTRL() -#define BX_INSTR_MOV_CR3 10 -#define BX_INSTR_INVLPG 11 -#define BX_INSTR_TASKSWITCH 12 - -// possible types passed to BX_INSTR_CACHE_CNTRL() -#define BX_INSTR_INVD 20 -#define BX_INSTR_WBINVD 21 - -#define BX_INSTR_IS_CALL 10 -#define BX_INSTR_IS_RET 11 -#define BX_INSTR_IS_IRET 12 -#define BX_INSTR_IS_JMP 13 -#define BX_INSTR_IS_INT 14 - -#define BX_INSTR_PREFETCH_NTA 00 -#define BX_INSTR_PREFETCH_T0 01 -#define BX_INSTR_PREFETCH_T1 02 -#define BX_INSTR_PREFETCH_T2 03 - - - - - -#if BX_INSTRUMENTATION - -class bxInstruction_c; - -// called from the CPU core - -void bx_instr_init(unsigned cpu); -void bx_instr_shutdown(unsigned cpu); -void bx_instr_reset(unsigned cpu); -void bx_instr_new_instruction(unsigned cpu); - -void bx_instr_debug_promt(); -void bx_instr_start(); -void bx_instr_stop(); -void bx_instr_print(); - -void bx_instr_cnear_branch_taken(unsigned cpu, bx_address new_eip); -void bx_instr_cnear_branch_not_taken(unsigned cpu); -void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address new_eip); -void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip); - -void bx_instr_opcode(unsigned cpu, Bit8u *opcode, unsigned len, bx_bool is32); -void bx_instr_fetch_decode_completed(unsigned cpu, const bxInstruction_c *i); - -void bx_instr_prefix_as(unsigned cpu); -void bx_instr_prefix_os(unsigned cpu); -void bx_instr_prefix_rep(unsigned cpu); -void bx_instr_prefix_repne(unsigned cpu); -void bx_instr_prefix_lock(unsigned cpu); -void bx_instr_prefix_cs(unsigned cpu); -void bx_instr_prefix_ss(unsigned cpu); -void bx_instr_prefix_ds(unsigned cpu); -void bx_instr_prefix_es(unsigned cpu); -void bx_instr_prefix_fs(unsigned cpu); -void bx_instr_prefix_gs(unsigned cpu); -void bx_instr_prefix_extend8b(unsigned cpu); - -void bx_instr_interrupt(unsigned cpu, unsigned vector); -void bx_instr_exception(unsigned cpu, unsigned vector); -void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip); - -void bx_instr_tlb_cntrl(unsigned cpu, unsigned what, Bit32u newval); -void bx_instr_cache_cntrl(unsigned cpu, unsigned what); -void bx_instr_prefetch_hint(unsigned cpu, unsigned what, unsigned seg, bx_address offset); - -void bx_instr_before_execution(unsigned cpu); -void bx_instr_after_execution(unsigned cpu); -void bx_instr_repeat_iteration(unsigned cpu); - -void bx_instr_inp(Bit16u addr, unsigned len); -void bx_instr_outp(Bit16u addr, unsigned len); -void bx_instr_inp2(Bit16u addr, unsigned len, unsigned val); -void bx_instr_outp2(Bit16u addr, unsigned len, unsigned val); - -void bx_instr_mem_code(unsigned cpu, bx_address linear, unsigned size); -void bx_instr_mem_data(unsigned cpu, bx_address linear, unsigned size, unsigned rw); - -void bx_instr_lin_read(unsigned cpu, bx_address lin, bx_address phy, unsigned len); -void bx_instr_lin_write(unsigned cpu, bx_address lin, bx_address phy, unsigned len); - -void bx_instr_phy_write(unsigned cpu, bx_address addr, unsigned len); -void bx_instr_phy_read(unsigned cpu, bx_address addr, unsigned len); - -/* simulation init, shutdown, reset */ -# define BX_INSTR_INIT(cpu_id) bx_instr_init(cpu_id) -# define BX_INSTR_SHUTDOWN(cpu_id) bx_instr_shutdown(cpu_id) -# define BX_INSTR_RESET(cpu_id) bx_instr_reset(cpu_id) -# define BX_INSTR_NEW_INSTRUCTION(cpu_id) bx_instr_new_instruction(cpu_id) - -/* called from command line debugger */ -# define BX_INSTR_DEBUG_PROMPT() bx_instr_debug_promt() -# define BX_INSTR_START() bx_instr_start() -# define BX_INSTR_STOP() bx_instr_stop() -# define BX_INSTR_PRINT() bx_instr_print() - -/* branch resoultion */ -# define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, new_eip) bx_instr_cnear_branch_taken(cpu_id, new_eip) -# define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id) bx_instr_cnear_branch_not_taken(cpu_id) -# define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, new_eip) bx_instr_ucnear_branch(cpu_id, what, new_eip) -# define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) bx_instr_far_branch(cpu_id, what, new_cs, new_eip) - -/* decoding completed */ -# define BX_INSTR_OPCODE(cpu_id, opcode, len, is32) \ - bx_instr_opcode(cpu_id, opcode, len, is32) -# define BX_INSTR_FETCH_DECODE_COMPLETED(cpu_id, i) \ - bx_instr_fetch_decode_completed(cpu_id, i) - -/* prefix decoded */ -# define BX_INSTR_PREFIX_AS(cpu_id) bx_instr_prefix_as(cpu_id) -# define BX_INSTR_PREFIX_OS(cpu_id) bx_instr_prefix_os(cpu_id) -# define BX_INSTR_PREFIX_REP(cpu_id) bx_instr_prefix_rep(cpu_id) -# define BX_INSTR_PREFIX_REPNE(cpu_id) bx_instr_prefix_repne(cpu_id) -# define BX_INSTR_PREFIX_LOCK(cpu_id) bx_instr_prefix_lock(cpu_id) -# define BX_INSTR_PREFIX_CS(cpu_id) bx_instr_prefix_cs(cpu_id) -# define BX_INSTR_PREFIX_SS(cpu_id) bx_instr_prefix_ss(cpu_id) -# define BX_INSTR_PREFIX_DS(cpu_id) bx_instr_prefix_ds(cpu_id) -# define BX_INSTR_PREFIX_ES(cpu_id) bx_instr_prefix_es(cpu_id) -# define BX_INSTR_PREFIX_FS(cpu_id) bx_instr_prefix_fs(cpu_id) -# define BX_INSTR_PREFIX_GS(cpu_id) bx_instr_prefix_gs(cpu_id) -# define BX_INSTR_PREFIX_EXTEND8B(cpu_id) bx_instr_prefix_extend8b(cpu_id) - -/* exceptional case and interrupt */ -# define BX_INSTR_EXCEPTION(cpu_id, vector) bx_instr_exception(cpu_id, vector) -# define BX_INSTR_INTERRUPT(cpu_id, vector) bx_instr_interrupt(cpu_id, vector) -# define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) bx_instr_hwinterrupt(cpu_id, vector, cs, eip) - -/* TLB/CACHE control instruction executed */ -# define BX_INSTR_CACHE_CNTRL(cpu_id, what) bx_instr_cache_cntrl(cpu_id, what) -# define BX_INSTR_TLB_CNTRL(cpu_id, what, newval) bx_instr_tlb_cntrl(cpu_id, what, newval) -# define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset) \ - bx_instr_prefetch_hint(cpu_id, what, seg, offset) - -/* execution */ -# define BX_INSTR_BEFORE_EXECUTION(cpu_id) bx_instr_before_execution(cpu_id) -# define BX_INSTR_AFTER_EXECUTION(cpu_id) bx_instr_after_execution(cpu_id) -# define BX_INSTR_REPEAT_ITERATION(cpu_id) bx_instr_repeat_iteration(cpu_id) - -/* memory access */ -# define BX_INSTR_LIN_READ(cpu_id, lin, phy, len) bx_instr_lin_read(cpu_id, lin, phy, len) -# define BX_INSTR_LIN_WRITE(cpu_id, lin, phy, len) bx_instr_lin_write(cpu_id, lin, phy, len) - -# define BX_INSTR_MEM_CODE(cpu_id, linear, size) bx_instr_mem_code(cpu_id, linear, size) -# define BX_INSTR_MEM_DATA(cpu_id, linear, size, rw) bx_instr_mem_data(cpu_id, linear, size, rw) - -/* called from memory object */ -# define BX_INSTR_PHY_WRITE(cpu_id, addr, len) bx_instr_phy_write(cpu_id, addr, len) -# define BX_INSTR_PHY_READ(cpu_id, addr, len) bx_instr_phy_read(cpu_id, addr, len) - -/* feedback from device units */ -# define BX_INSTR_INP(addr, len) bx_instr_inp(addr, len) -# define BX_INSTR_INP2(addr, len, val) bx_instr_inp2(addr, len, val) -# define BX_INSTR_OUTP(addr, len) bx_instr_outp(addr, len) -# define BX_INSTR_OUTP2(addr, len, val) bx_instr_outp2(addr, len, val) - -#else - -/* simulation init, shutdown, reset */ -# define BX_INSTR_INIT(cpu_id) -# define BX_INSTR_SHUTDOWN(cpu_id) -# define BX_INSTR_RESET(cpu_id) -# define BX_INSTR_NEW_INSTRUCTION(cpu_id) - -/* called from command line debugger */ -# define BX_INSTR_DEBUG_PROMPT() -# define BX_INSTR_START() -# define BX_INSTR_STOP() -# define BX_INSTR_PRINT() - -/* branch resoultion */ -# define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, new_eip) -# define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id) -# define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, new_eip) -# define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) - -/* decoding completed */ -# define BX_INSTR_OPCODE(cpu_id, opcode, len, is32) -# define BX_INSTR_FETCH_DECODE_COMPLETED(cpu_id, i) - -/* prefix decoded */ -# define BX_INSTR_PREFIX_AS(cpu_id) -# define BX_INSTR_PREFIX_OS(cpu_id) -# define BX_INSTR_PREFIX_REP(cpu_id) -# define BX_INSTR_PREFIX_REPNE(cpu_id) -# define BX_INSTR_PREFIX_LOCK(cpu_id) -# define BX_INSTR_PREFIX_CS(cpu_id) -# define BX_INSTR_PREFIX_SS(cpu_id) -# define BX_INSTR_PREFIX_DS(cpu_id) -# define BX_INSTR_PREFIX_ES(cpu_id) -# define BX_INSTR_PREFIX_FS(cpu_id) -# define BX_INSTR_PREFIX_GS(cpu_id) -# define BX_INSTR_PREFIX_EXTEND8B(cpu_id) - -/* exceptional case and interrupt */ -# define BX_INSTR_EXCEPTION(cpu_id, vector) -# define BX_INSTR_INTERRUPT(cpu_id, vector) -# define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) - -/* TLB/CACHE control instruction executed */ -# define BX_INSTR_CACHE_CNTRL(cpu_id, what) -# define BX_INSTR_TLB_CNTRL(cpu_id, what, newval) -# define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset) - -/* execution */ -# define BX_INSTR_BEFORE_EXECUTION(cpu_id) -# define BX_INSTR_AFTER_EXECUTION(cpu_id) -# define BX_INSTR_REPEAT_ITERATION(cpu_id) - -/* memory access */ -# define BX_INSTR_LIN_READ(cpu_id, lin, phy, len) -# define BX_INSTR_LIN_WRITE(cpu_id, lin, phy, len) - -# define BX_INSTR_MEM_CODE(cpu_id, linear, size) -# define BX_INSTR_MEM_DATA(cpu_id, linear, size, rw) - -/* called from memory object */ -# define BX_INSTR_PHY_WRITE(cpu_id, addr, len) -# define BX_INSTR_PHY_READ(cpu_id, addr, len) - -/* feedback from device units */ -# define BX_INSTR_INP(addr, len) -# define BX_INSTR_INP2(addr, len, val) -# define BX_INSTR_OUTP(addr, len) -# define BX_INSTR_OUTP2(addr, len, val) - -#endif diff --git a/tools/ioemu/include/ltdl.h b/tools/ioemu/include/ltdl.h deleted file mode 100644 index 3a02b311c2..0000000000 --- a/tools/ioemu/include/ltdl.h +++ /dev/null @@ -1,398 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: ltdl.h,v 1.2 2002/10/24 21:04:37 bdenney Exp $ -// -// NOTE: The ltdl library comes from the Libtool package. Bochs uses -// ltdl and libtool to build and load plugins. The libtool -// documentation describes how to copy ltdl.c and ltdl.h into your -// distribution, so it is clearly legal to do so. -///////////////////////////////////////////////////////////////////////// - -/* ltdl.h -- generic dlopen functions - Copyright (C) 1998-2000 Free Software Foundation, Inc. - Originally by Thomas Tanner - This file is part of GNU Libtool. - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2 of the License, or (at your option) any later version. - -As a special exception to the GNU Lesser General Public License, -if you distribute this file as part of a program or library that -is built using GNU libtool, you may include it under the same -distribution terms that you use for the rest of that program. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free -Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA -02111-1307 USA -*/ - -/* Only include this header file once. */ -#ifndef LTDL_H -#define LTDL_H 1 - -#ifdef __cplusplus -extern "C" { -#endif -#include /* for size_t declaration */ -#ifdef __cplusplus -}; -#endif - - -/* --- MACROS FOR PORTABILITY --- */ - - -/* Saves on those hard to debug '\0' typos.... */ -#define LT_EOS_CHAR '\0' - -/* LTDL_BEGIN_C_DECLS should be used at the beginning of your declarations, - so that C++ compilers don't mangle their names. Use LTDL_END_C_DECLS at - the end of C declarations. */ -#ifdef __cplusplus -# define LT_BEGIN_C_DECLS extern "C" { -# define LT_END_C_DECLS } -#else -# define LT_BEGIN_C_DECLS /* empty */ -# define LT_END_C_DECLS /* empty */ -#endif - -LT_BEGIN_C_DECLS - - -/* LT_PARAMS is a macro used to wrap function prototypes, so that compilers - that don't understand ANSI C prototypes still work, and ANSI C - compilers can issue warnings about type mismatches. */ -#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32) || defined(__cplusplus) -# define LT_PARAMS(protos) protos -# define lt_ptr void* -#else -# define LT_PARAMS(protos) () -# define lt_ptr char* -#endif - -/* LT_STMT_START/END are used to create macros which expand to a - a single compound statement in a portable way. */ -#if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus) -# define LT_STMT_START (void)( -# define LT_STMT_END ) -#else -# if (defined (sun) || defined (__sun__)) -# define LT_STMT_START if (1) -# define LT_STMT_END else (void)0 -# else -# define LT_STMT_START do -# define LT_STMT_END while (0) -# endif -#endif - -/* LT_CONC creates a new concatenated symbol for the compiler - in a portable way. */ -#if defined(__STDC__) || defined(__cplusplus) -# define LT_CONC(s,t) s##t -#else -# define LT_CONC(s,t) s/**/t -#endif - -/* LT_STRLEN can be used safely on NULL pointers. */ -#define LT_STRLEN(s) (((s) && (s)[0]) ? strlen (s) : 0) - - - -/* --- WINDOWS SUPPORT --- */ - - -/* Canonicalise Windows and Cygwin recognition macros. */ -#ifdef __CYGWIN32__ -# ifndef __CYGWIN__ -# define __CYGWIN__ __CYGWIN32__ -# endif -#endif -#if defined(_WIN32) || defined(WIN32) -# ifndef __WINDOWS__ -# ifdef _WIN32 -# define __WINDOWS__ _WIN32 -# else -# ifdef WIN32 -# define __WINDOWS__ WIN32 -# endif -# endif -# endif -#endif - -#ifdef __WINDOWS__ -# ifndef __CYGWIN__ -/* LT_DIRSEP_CHAR is accepted *in addition* to '/' as a directory - separator when it is set. */ -# define LT_DIRSEP_CHAR '\\' -# define LT_PATHSEP_CHAR ';' -# endif -#endif -#ifndef LT_PATHSEP_CHAR -# define LT_PATHSEP_CHAR ':' -#endif - -/* DLL building support on win32 hosts; mostly to workaround their - ridiculous implementation of data symbol exporting. */ -#ifndef LT_SCOPE -# ifdef __WINDOWS__ -# ifdef DLL_EXPORT /* defined by libtool (if required) */ -# define LT_SCOPE __declspec(dllexport) -# endif -# ifdef LIBLTDL_DLL_IMPORT /* define if linking with this dll */ -# define LT_SCOPE extern __declspec(dllimport) -# endif -# endif -# ifndef LT_SCOPE /* static linking or !__WINDOWS__ */ -# define LT_SCOPE extern -# endif -#endif - - - - -/* --- DYNAMIC MODULE LOADING API --- */ - - -typedef struct lt_dlhandle_struct *lt_dlhandle; /* A loaded module. */ - -/* Initialisation and finalisation functions for libltdl. */ -extern int lt_dlinit LT_PARAMS((void)); -extern int lt_dlexit LT_PARAMS((void)); - -/* Module search path manipulation. */ -extern int lt_dladdsearchdir LT_PARAMS((const char *search_dir)); -extern int lt_dlinsertsearchdir LT_PARAMS((const char *before, - const char *search_dir)); -extern int lt_dlsetsearchpath LT_PARAMS((const char *search_path)); -extern const char *lt_dlgetsearchpath LT_PARAMS((void)); -extern int lt_dlforeachfile LT_PARAMS(( - const char *search_path, - int (*func) (const char *filename, lt_ptr data), - lt_ptr data)); - -/* Portable libltdl versions of the system dlopen() API. */ -extern lt_dlhandle lt_dlopen LT_PARAMS((const char *filename)); -extern lt_dlhandle lt_dlopenext LT_PARAMS((const char *filename)); -extern lt_ptr lt_dlsym LT_PARAMS((lt_dlhandle handle, - const char *name)); -extern const char *lt_dlerror LT_PARAMS((void)); -extern int lt_dlclose LT_PARAMS((lt_dlhandle handle)); - -/* Module residency management. */ -extern int lt_dlmakeresident LT_PARAMS((lt_dlhandle handle)); -extern int lt_dlisresident LT_PARAMS((lt_dlhandle handle)); - - - - -/* --- MUTEX LOCKING --- */ - - -typedef void lt_dlmutex_lock LT_PARAMS((void)); -typedef void lt_dlmutex_unlock LT_PARAMS((void)); -typedef void lt_dlmutex_seterror LT_PARAMS((const char *errmsg)); -typedef const char *lt_dlmutex_geterror LT_PARAMS((void)); - -extern int lt_dlmutex_register LT_PARAMS((lt_dlmutex_lock *lock, - lt_dlmutex_unlock *unlock, - lt_dlmutex_seterror *seterror, - lt_dlmutex_geterror *geterror)); - - - - -/* --- MEMORY HANDLING --- */ - - -/* By default, the realloc function pointer is set to our internal - realloc implementation which iself uses lt_dlmalloc and lt_dlfree. - libltdl relies on a featureful realloc, but if you are sure yours - has the right semantics then you can assign it directly. Generally, - it is safe to assign just a malloc() and a free() function. */ -LT_SCOPE lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size)); -LT_SCOPE lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size)); -LT_SCOPE void (*lt_dlfree) LT_PARAMS((lt_ptr ptr)); - - - - -/* --- PRELOADED MODULE SUPPORT --- */ - - -/* A preopened symbol. Arrays of this type comprise the exported - symbols for a dlpreopened module. */ -typedef struct { - const char *name; - lt_ptr address; -} lt_dlsymlist; - -extern int lt_dlpreload LT_PARAMS((const lt_dlsymlist *preloaded)); -extern int lt_dlpreload_default - LT_PARAMS((const lt_dlsymlist *preloaded)); - -#define LTDL_SET_PRELOADED_SYMBOLS() LT_STMT_START{ \ - extern const lt_dlsymlist lt_preloaded_symbols[]; \ - lt_dlpreload_default(lt_preloaded_symbols); \ - }LT_STMT_END - - - - -/* --- MODULE INFORMATION --- */ - - -/* Read only information pertaining to a loaded module. */ -typedef struct { - char *filename; /* file name */ - char *name; /* module name */ - int ref_count; /* number of times lt_dlopened minus - number of times lt_dlclosed. */ -} lt_dlinfo; - -extern const lt_dlinfo *lt_dlgetinfo LT_PARAMS((lt_dlhandle handle)); -extern lt_dlhandle lt_dlhandle_next LT_PARAMS((lt_dlhandle place)); -extern int lt_dlforeach LT_PARAMS(( - int (*func) (lt_dlhandle handle, lt_ptr data), - lt_ptr data)); - -/* Associating user data with loaded modules. */ -typedef unsigned lt_dlcaller_id; - -extern lt_dlcaller_id lt_dlcaller_register LT_PARAMS((void)); -extern lt_ptr lt_dlcaller_set_data LT_PARAMS((lt_dlcaller_id key, - lt_dlhandle handle, - lt_ptr data)); -extern lt_ptr lt_dlcaller_get_data LT_PARAMS((lt_dlcaller_id key, - lt_dlhandle handle)); - - - -/* --- USER MODULE LOADER API --- */ - - -typedef struct lt_dlloader lt_dlloader; -typedef lt_ptr lt_user_data; -typedef lt_ptr lt_module; - -/* Function pointer types for creating user defined module loaders. */ -typedef lt_module lt_module_open LT_PARAMS((lt_user_data loader_data, - const char *filename)); -typedef int lt_module_close LT_PARAMS((lt_user_data loader_data, - lt_module handle)); -typedef lt_ptr lt_find_sym LT_PARAMS((lt_user_data loader_data, - lt_module handle, - const char *symbol)); -typedef int lt_dlloader_exit LT_PARAMS((lt_user_data loader_data)); - -struct lt_user_dlloader { - const char *sym_prefix; - lt_module_open *module_open; - lt_module_close *module_close; - lt_find_sym *find_sym; - lt_dlloader_exit *dlloader_exit; - lt_user_data dlloader_data; -}; - -extern lt_dlloader *lt_dlloader_next LT_PARAMS((lt_dlloader *place)); -extern lt_dlloader *lt_dlloader_find LT_PARAMS(( - const char *loader_name)); -extern const char *lt_dlloader_name LT_PARAMS((lt_dlloader *place)); -extern lt_user_data *lt_dlloader_data LT_PARAMS((lt_dlloader *place)); -extern int lt_dlloader_add LT_PARAMS((lt_dlloader *place, - const struct lt_user_dlloader *dlloader, - const char *loader_name)); -extern int lt_dlloader_remove LT_PARAMS(( - const char *loader_name)); - - - -/* --- ERROR MESSAGE HANDLING --- */ - -/* Bryce rewrote the error table in a way that would be likely to work - on all compilers. VC++ was not able to handle it the way it was - done originally. */ - -/* ORIG COMMENT: Defining error strings alongside their symbolic names in a - macro in this way allows us to expand the macro in different contexts with - confidence that the enumeration of symbolic names will map correctly - onto the table of error strings. */ - -#define lt_dlerror_symbols_list \ - LT_ERROR_UNKNOWN, \ - LT_ERROR_DLOPEN_NOT_SUPPORTED, \ - LT_ERROR_INVALID_LOADER, \ - LT_ERROR_INIT_LOADER, \ - LT_ERROR_REMOVE_LOADER, \ - LT_ERROR_FILE_NOT_FOUND, \ - LT_ERROR_DEPLIB_NOT_FOUND, \ - LT_ERROR_NO_SYMBOLS, \ - LT_ERROR_CANNOT_OPEN, \ - LT_ERROR_CANNOT_CLOSE, \ - LT_ERROR_SYMBOL_NOT_FOUND, \ - LT_ERROR_NO_MEMORY, \ - LT_ERROR_INVALID_HANDLE, \ - LT_ERROR_BUFFER_OVERFLOW, \ - LT_ERROR_INVALID_ERRORCODE, \ - LT_ERROR_SHUTDOWN, \ - LT_ERROR_CLOSE_RESIDENT_MODULE, \ - LT_ERROR_INVALID_MUTEX_ARGS, \ - LT_ERROR_INVALID_POSITION, - -#define lt_dlerror_names_list \ - "unknown error", \ - "dlopen support not available", \ - "invalid loader", \ - "loader initialization failed", \ - "loader removal failed", \ - "file not found", \ - "dependency library not found", \ - "no symbols defined", \ - "can't open the module", \ - "can't close the module", \ - "symbol not found", \ - "not enough memory", \ - "invalid module handle", \ - "internal buffer overflow", \ - "invalid errorcode", \ - "library already shutdown", \ - "can't close resident module", \ - "invalid mutex handler registration", \ - "invalid search path insert position", - -/* Enumerate the symbolic error names. */ -enum { - lt_dlerror_symbols_list - LT_ERROR_MAX -}; - -/* These functions are only useful from inside custom module loaders. */ -extern int lt_dladderror LT_PARAMS((const char *diagnostic)); -extern int lt_dlseterror LT_PARAMS((int errorcode)); - - - - -/* --- SOURCE COMPATIBILITY WITH OLD LIBLTDL --- */ - - -#ifdef LT_NON_POSIX_NAMESPACE -# define lt_ptr_t lt_ptr -# define lt_module_t lt_module -# define lt_module_open_t lt_module_open -# define lt_module_close_t lt_module_close -# define lt_find_sym_t lt_find_sym -# define lt_dlloader_exit_t lt_dlloader_exit -# define lt_dlloader_t lt_dlloader -# define lt_dlloader_data_t lt_user_data -#endif - -LT_END_C_DECLS - -#endif /* !LTDL_H */ diff --git a/tools/ioemu/include/ltdlconf.h b/tools/ioemu/include/ltdlconf.h deleted file mode 100644 index 5ffd0e7916..0000000000 --- a/tools/ioemu/include/ltdlconf.h +++ /dev/null @@ -1,161 +0,0 @@ -/* ltdlconf.h. Generated by configure. */ -///////////////////////////////////////////////////////////////////////// -// $Id: ltdlconf.h.in,v 1.2 2002/10/24 21:04:38 bdenney Exp $ -// -// The configure script reads this file and produces ltdlconf.h, which -// tells ltdl.c how to compile. It was copied out of the libtool package -// but appears to have been generated by autoheader. -///////////////////////////////////////////////////////////////////////// - -/* config-h.in. Generated automatically from configure.in by autoheader. */ - -/* Define to empty if the keyword does not work. */ -/* #undef const */ - -/* Define as __inline if that's what the C compiler calls it. */ -/* #undef inline */ - -/* Define if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define if you have the argz_append function. */ -#define HAVE_ARGZ_APPEND 1 - -/* Define if you have the argz_create_sep function. */ -#define HAVE_ARGZ_CREATE_SEP 1 - -/* Define if you have the argz_insert function. */ -#define HAVE_ARGZ_INSERT 1 - -/* Define if you have the argz_next function. */ -#define HAVE_ARGZ_NEXT 1 - -/* Define if you have the argz_stringify function. */ -#define HAVE_ARGZ_STRINGIFY 1 - -/* Define if you have the bcopy function. */ -/* #undef HAVE_BCOPY */ - -/* Define if you have the dlerror function. */ -#define HAVE_DLERROR 1 - -/* Define if you have the index function. */ -/* #undef HAVE_INDEX */ - -/* Define if you have the memcpy function. */ -#define HAVE_MEMCPY 1 - -/* Define if you have the memmove function. */ -#define HAVE_MEMMOVE 1 - -/* Define if you have the rindex function. */ -/* #undef HAVE_RINDEX */ - -/* Define if you have the strchr function. */ -#define HAVE_STRCHR 1 - -/* Define if you have the strcmp function. */ -#define HAVE_STRCMP 1 - -/* Define if you have the strrchr function. */ -#define HAVE_STRRCHR 1 - -/* Define if you have the header file. */ -#define HAVE_ARGZ_H 1 - -/* Define if you have the header file. */ -#define HAVE_ASSERT_H 1 - -/* Define if you have the header file. */ -#define HAVE_CTYPE_H 1 - -/* Define if you have the header file. */ -#define HAVE_DIRENT_H 1 - -/* Define if you have the header file. */ -/* #undef HAVE_DL_H */ - -/* Define if you have the header file. */ -/* #undef HAVE_DLD_H */ - -/* Define if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define if you have the header file. */ -#define HAVE_ERRNO_H 1 - -/* Define if you have the header file. */ -#define HAVE_MALLOC_H 1 - -/* Define if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define if you have the header file. */ -/* #undef HAVE_NDIR_H */ - -/* Define if you have the header file. */ -#define HAVE_STDIO_H 1 - -/* Define if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define if you have the header file. */ -/* #undef HAVE_SYS_DIR_H */ - -/* Define if you have the header file. */ -/* #undef HAVE_SYS_DL_H */ - -/* Define if you have the header file. */ -/* #undef HAVE_SYS_NDIR_H */ - -/* Define if you have the header file. */ -#define HAVE_UNISTD_H 1 - -/* Define to the extension used for shared libraries, say, .so. */ -#define LTDL_SHLIB_EXT ".so" - -/* Define to the name of the environment variable that determines the dynamic library search path. */ -#define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH" - -/* Define to the system default library search path. */ -#define LTDL_SYSSEARCHPATH "/lib:/usr/lib" - -/* Define to the sub-directory in which libtool stores uninstalled libraries. */ -#define LTDL_OBJDIR ".libs/" - -/* Define if libtool can extract symbol lists from object files. */ -#define HAVE_PRELOADED_SYMBOLS 1 - -/* Define if you have the libdl library or equivalent. */ -#define HAVE_LIBDL 1 - -/* Define if you have the libdl library or equivalent. */ -#define HAVE_LIBDL 1 - -/* Define if you have the libdl library or equivalent. */ -#define HAVE_LIBDL 1 - -/* Define if you have the shl_load function. */ -/* #undef HAVE_SHL_LOAD */ - -/* Define if you have the shl_load function. */ -/* #undef HAVE_SHL_LOAD */ - -/* Define if you have the GNU dld library. */ -/* #undef HAVE_DLD */ - -/* Define if dlsym() requires a leading underscode in symbol names. */ -/* #undef NEED_USCORE */ - -/* Define if the OS needs help to load dependent libraries for dlopen(). */ -/* #undef LTDL_DLOPEN_DEPLIBS */ - -/* Define to a type to use for `error_t' if it is not otherwise available. */ -/* #undef error_t */ - diff --git a/tools/ioemu/include/osdep.h b/tools/ioemu/include/osdep.h deleted file mode 100644 index a47b88d06e..0000000000 --- a/tools/ioemu/include/osdep.h +++ /dev/null @@ -1,176 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: osdep.h,v 1.19 2003/08/20 06:26:27 japj Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// -// osdep.h -// -// requires Bit32u/Bit64u from config.h, size_t from stdio.h -// -// Operating system dependent includes and defines for Bochs. These -// declarations can be included by C or C++., but they require definition of -// size_t beforehand. This makes it difficult to place them into either -// config.h or bochs.h. If in config.h, size_t is not always available yet. -// If in bochs.h, they can't be included by C programs so they lose. -// - -#ifndef BX_OSDEP_H -#define BX_OSDEP_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -////////////////////////////////////////////////////////////////////// -// Hacks for win32, but exclude MINGW32 because it doesn't need them. -////////////////////////////////////////////////////////////////////// -#ifdef WIN32 - -// Definitions that are needed for all WIN32 compilers. -# define ssize_t long - -#ifndef __MINGW32__ -#define FMT_LL "%I64" - -// Definitions that are needed for WIN32 compilers EXCEPT FOR -// cygwin compiling with -mno-cygwin. e.g. VC++. - -// always return regular file. -# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) -# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR) - -// win32 has snprintf though with different name. -#define snprintf _snprintf -#else /* ifnndef __MINGW32__ */ -#define FMT_LL "%ll" -#endif /* ifnndef __MINGW32__ */ -#else /* WIN32 */ -#define FMT_LL "%ll" -#endif /* WIN32 */ - -// Missing defines for open -#ifndef S_IRUSR -#define S_IRUSR 0400 -#define S_IWUSR 0200 -#endif -#ifndef S_IRGRP -#define S_IRGRP 0040 -#define S_IWGRP 0020 -#endif -#ifndef S_IROTH -#define S_IROTH 0004 -#define S_IWOTH 0002 -#endif - -////////////////////////////////////////////////////////////////////// -// Missing library functions. -// These should work on any platform that needs them. -// -// A missing library function is renamed to a bx_* function, so that when -// debugging and linking there's no confusion over which version is used. -// Because of renaming, the bx_* replacement functions can be tested on -// machines which have the real library function without duplicate symbols. -// -// If you're considering implementing a missing library function, note -// that it might be cleaner to conditionally disable the function call! -////////////////////////////////////////////////////////////////////// - -#if !BX_HAVE_SNPRINTF -#define snprintf bx_snprintf - extern int bx_snprintf (char *s, size_t maxlen, const char *format, ...); -#endif - -#if BX_HAVE_STRTOULL - // great, just use the usual function -#elif BX_HAVE_STRTOUQ - // they have strtouq and not strtoull - #define strtoull strtouq -#else - #define strtoull bx_strtoull - extern Bit64u bx_strtoull (const char *nptr, char **endptr, int baseignore); -#endif - -#if !BX_HAVE_STRDUP -#define strdup bx_strdup - extern char *bx_strdup(const char *str); -#endif - -#if !BX_HAVE_STRREV -#define strrev bx_strrev - extern char *bx_strrev(char *str); -#endif - -#if !BX_HAVE_SOCKLEN_T -// needed on MacOS X 10.1 -typedef int socklen_t; -#endif - -#if !BX_HAVE_MKSTEMP -#define mkstemp bx_mkstemp - extern int bx_mkstemp(char *tpl); -#endif - -////////////////////////////////////////////////////////////////////// -// Missing library functions, implemented for MacOS only -////////////////////////////////////////////////////////////////////// - -#if BX_WITH_MACOS -// fd_read and fd_write are called by floppy.cc to access the Mac -// floppy drive directly, since the MacOS doesn't have "special" -// pathnames which map directly to IO devices - -int fd_read(char *buffer, Bit32u offset, Bit32u bytes); -int fd_write(char *buffer, Bit32u offset, Bit32u bytes); -int fd_stat(struct stat *buf); -FILE * fdopen(int fd, const char *type); - -typedef long ssize_t ; -#endif - -////////////////////////////////////////////////////////////////////// -// New functions to replace library functions -// with OS-independent versions -////////////////////////////////////////////////////////////////////// - -#if BX_HAVE_REALTIME_USEC -// 64-bit time in useconds. -extern Bit64u bx_get_realtime64_usec (void); -#endif - -#ifdef WIN32 -#undef BX_HAVE_MSLEEP -#define BX_HAVE_MSLEEP 1 -#ifndef __MINGW32__ -#define msleep(msec) _sleep(msec) -#else -#define msleep(msec) Sleep(msec) -#endif -#endif - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* ifdef BX_OSDEP_H */ diff --git a/tools/ioemu/include/pc_system.h b/tools/ioemu/include/pc_system.h deleted file mode 100644 index c8ea664577..0000000000 --- a/tools/ioemu/include/pc_system.h +++ /dev/null @@ -1,226 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pc_system.h,v 1.25 2003/03/02 23:59:08 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - - -#define BX_MAX_TIMERS 64 -#define BX_NULL_TIMER_HANDLE 10000 - - -#if BX_SHOW_IPS -extern unsigned long ips_count; -#endif - - -typedef void (*bx_timer_handler_t)(void *); - - -BOCHSAPI extern class bx_pc_system_c bx_pc_system; - -#ifdef PROVIDE_M_IPS -extern double m_ips; -#endif - -#ifdef BX_USE_VMX -extern unsigned int tsc_per_bx_tick; - -#define rdtscll(val) \ - __asm__ __volatile__("rdtsc" : "=A" (val)) -#endif - -class BOCHSAPI bx_pc_system_c : private logfunctions { -private: - - // =============================== - // Timer oriented private features - // =============================== - - struct { - bx_bool inUse; // Timer slot is in-use (currently registered). - Bit64u period; // Timer periodocity in cpu ticks. - Bit64u timeToFire; // Time to fire next (in absolute ticks). - bx_bool active; // 0=inactive, 1=active. - bx_bool continuous; // 0=one-shot timer, 1=continuous periodicity. - bx_timer_handler_t funct; // A callback function for when the - // timer fires. - void *this_ptr; // The this-> pointer for C++ callbacks - // has to be stored as well. -#define BxMaxTimerIDLen 32 - char id[BxMaxTimerIDLen]; // String ID of timer. - } timer[BX_MAX_TIMERS]; - - unsigned numTimers; // Number of currently allocated timers. - Bit32u currCountdown; // Current countdown ticks value (decrements to 0). - Bit32u currCountdownPeriod; // Length of current countdown period. - Bit64u ticksTotal; // Num ticks total since start of emulator execution. - Bit64u lastTimeUsec; // Last sequentially read time in usec. - Bit64u usecSinceLast; // Number of useconds claimed since then. - - // A special null timer is always inserted in the timer[0] slot. This - // make sure that at least one timer is always active, and that the - // duration is always less than a maximum 32-bit integer, so a 32-bit - // counter can be used for the current countdown. - static const Bit64u NullTimerInterval; - static void nullTimer(void* this_ptr); - -#if !defined(PROVIDE_M_IPS) - // This is the emulator speed, as measured in millions of - // x86 instructions per second that it can emulate on some hypothetically - // nomimal workload. - double m_ips; // Millions of Instructions Per Second -#endif - -#ifdef BX_USE_VMX - static Bit64s get_clock(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000000LL + tv.tv_usec; - } - - static Bit64u cpu_calibrate_ticks(void) { - Bit64s usec, t1, t2; - - usec = get_clock(); - rdtscll(t1); - - usleep(50 * 1000); - usec = get_clock() - usec; - rdtscll(t2); - - return (((t2 - t1) * 1000000LL + (usec >> 1)) / usec); - } -#endif - // This handler is called when the function which decrements the clock - // ticks finds that an event has occurred. - void countdownEvent(void); - -public: - - // ============================== - // Timer oriented public features - // ============================== - - void init_ips(Bit32u ips); - int register_timer( void *this_ptr, bx_timer_handler_t, Bit32u useconds, - bx_bool continuous, bx_bool active, const char *id); - unsigned unregisterTimer(int timerID); - void start_timers(void); - void activate_timer( unsigned timer_index, Bit32u useconds, - bx_bool continuous ); - void deactivate_timer( unsigned timer_index ); - static BX_CPP_INLINE void tick1(void) { -#if BX_SHOW_IPS - { - extern unsigned long ips_count; - ips_count++; - } -#endif - if (--bx_pc_system.currCountdown == 0) { - bx_pc_system.countdownEvent(); - } - } - static BX_CPP_INLINE void tickn(Bit64u n) { -#if BX_SHOW_IPS - { - extern unsigned long ips_count; - ips_count += n; - } -#endif - while (n >= Bit64u(bx_pc_system.currCountdown)) { - n -= Bit64u(bx_pc_system.currCountdown); - bx_pc_system.currCountdown = 0; - bx_pc_system.countdownEvent(); - // bx_pc_system.currCountdown is adjusted to new value by countdownevent(). - }; - // 'n' is not (or no longer) >= the countdown size. We can just decrement - // the remaining requested ticks and continue. - bx_pc_system.currCountdown -= Bit32u(n); - } - - int register_timer_ticks(void* this_ptr, bx_timer_handler_t, Bit64u ticks, - bx_bool continuous, bx_bool active, const char *id); - void activate_timer_ticks(unsigned index, Bit64u instructions, - bx_bool continuous); - Bit64u time_usec(); - Bit64u time_usec_sequential(); - static BX_CPP_INLINE Bit64u time_ticks() { - return bx_pc_system.ticksTotal + - Bit64u(bx_pc_system.currCountdownPeriod - bx_pc_system.currCountdown); - } - static BX_CPP_INLINE Bit64u getTicksTotal(void) { - return bx_pc_system.ticksTotal; - } - - static BX_CPP_INLINE Bit32u getNumCpuTicksLeftNextEvent(void) { - return bx_pc_system.currCountdown; - } -#if BX_DEBUGGER - static void timebp_handler(void* this_ptr); -#endif - - - // =========================== - // Non-timer oriented features - // =========================== - - bx_bool HRQ; // Hold Request - //bx_bool INTR; // Interrupt - - - // Address line 20 control: - // 1 = enabled: extended memory is accessible - // 0 = disabled: A20 address line is forced low to simulate - // an 8088 address map - bx_bool enable_a20; - - // start out masking physical memory addresses to: - // 8086: 20 bits - // 286: 24 bits - // 386: 32 bits - // when A20 line is disabled, mask physical memory addresses to: - // 286: 20 bits - // 386: 20 bits - // - Bit32u a20_mask; - - void set_HRQ(bx_bool val); // set the Hold ReQuest line - void set_INTR(bx_bool value); // set the INTR line to value - - int IntEnabled( void ); - int InterruptSignal( PCS_OP operation ); - int ResetSignal( PCS_OP operation ); - Bit8u IAC(void); - - bx_pc_system_c(void); - - Bit32u inp(Bit16u addr, unsigned io_len) BX_CPP_AttrRegparmN(2); - void outp(Bit16u addr, Bit32u value, unsigned io_len) BX_CPP_AttrRegparmN(3); - void set_enable_a20(Bit8u value) BX_CPP_AttrRegparmN(1); - bx_bool get_enable_a20(void); - void exit(void); - - }; diff --git a/tools/ioemu/include/plugin.h b/tools/ioemu/include/plugin.h deleted file mode 100644 index dabd13fdcc..0000000000 --- a/tools/ioemu/include/plugin.h +++ /dev/null @@ -1,323 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: plugin.h,v 1.20 2003/08/04 16:03:08 akrisak Exp $ -///////////////////////////////////////////////////////////////////////// -// -// This file provides macros and types needed for plugins. It is based on -// the plugin.h file from plex86, but with significant changes to make -// it work in Bochs. -// Plex86 is Copyright (C) 1999-2000 The plex86 developers team -// -///////////////////////////////////////////////////////////////////////// - -#ifndef __PLUGIN_H -#define __PLUGIN_H - -#include "extplugin.h" - -class bx_devices_c; -BOCHSAPI extern logfunctions *pluginlog; - -#ifdef __cplusplus -extern "C" { -#endif - -#define BX_PLUGIN_UNMAPPED "unmapped" -#define BX_PLUGIN_BIOSDEV " biosdev" -#define BX_PLUGIN_CMOS "cmos" -#define BX_PLUGIN_VGA "vga" -#define BX_PLUGIN_FLOPPY "floppy" -#define BX_PLUGIN_PARALLEL "parallel" -#define BX_PLUGIN_SERIAL "serial" -#define BX_PLUGIN_KEYBOARD "keyboard" -#define BX_PLUGIN_HARDDRV "harddrv" -#define BX_PLUGIN_DMA "dma" -#define BX_PLUGIN_PIC "pic" -#define BX_PLUGIN_PCI "pci" -#define BX_PLUGIN_PCI2ISA "pci2isa" -#define BX_PLUGIN_SB16 "sb16" -#define BX_PLUGIN_NE2K "ne2k" -#define BX_PLUGIN_EXTFPUIRQ "extfpuirq" -#define BX_PLUGIN_PCIVGA "pcivga" -#define BX_PLUGIN_PCIUSB "pciusb" -#define BX_PLUGIN_GAMEPORT "gameport" - - -#define BX_REGISTER_DEVICE_DEVMODEL(a,b,c,d) pluginRegisterDeviceDevmodel(a,b,c,d) - -#if BX_PLUGINS - -#define DEV_init_devices() {bx_devices.init(BX_MEM(0)); } -#define DEV_reset_devices(type) {bx_devices.reset(type); } -#define PLUG_load_plugin(name,type) {bx_load_plugin(#name,type);} - -#define DEV_register_ioread_handler(b,c,d,e,f) pluginRegisterIOReadHandler(b,c,d,e,f) -#define DEV_register_iowrite_handler(b,c,d,e,f) pluginRegisterIOWriteHandler(b,c,d,e,f) -#define DEV_register_default_ioread_handler(b,c,d,e) pluginRegisterDefaultIOReadHandler(b,c,d,e) -#define DEV_register_default_iowrite_handler(b,c,d,e) pluginRegisterDefaultIOWriteHandler(b,c,d,e) - -#define DEV_register_irq(b,c) pluginRegisterIRQ(b,c) -#define DEV_unregister_irq(b,c) pluginUnregisterIRQ(b,c) - -#else - -#define DEV_init_devices() {bx_devices.init(BX_MEM(0)); } -#define DEV_reset_devices(type) {bx_devices.reset(type); } -// When plugins are off, PLUG_load_plugin will call the plugin_init function -// directly. -#define PLUG_load_plugin(name,type) {lib##name##_LTX_plugin_init(NULL,type,0,NULL);} -#define DEV_register_ioread_handler(b,c,d,e,f) bx_devices.register_io_read_handler(b,c,d,e,f) -#define DEV_register_iowrite_handler(b,c,d,e,f) bx_devices.register_io_write_handler(b,c,d,e,f) -#define DEV_register_default_ioread_handler(b,c,d,e) bx_devices.register_default_io_read_handler(b,c,d,e) -#define DEV_register_default_iowrite_handler(b,c,d,e) bx_devices.register_default_io_write_handler(b,c,d,e) -#define DEV_register_irq(b,c) bx_devices.register_irq(b,c) -#define DEV_unregister_irq(b,c) bx_devices.unregister_irq(b,c) - -#endif // #if BX_PLUGINS - -#define DEV_ioapic_present() (bx_devices.ioapic != NULL) - -// FIXME Do we really need pluginRegisterTimer ? -#define DEV_register_timer(a,b,c,d,e,f) bx_pc_system.register_timer(a,b,c,d,e,f) - -///////// CMOS macros -#define DEV_cmos_get_reg(a) (bx_devices.pluginCmosDevice->get_reg(a)) -#define DEV_cmos_set_reg(a,b) (bx_devices.pluginCmosDevice->set_reg(a,b)) -#define DEV_cmos_checksum() (bx_devices.pluginCmosDevice->checksum_cmos()) -#define DEV_cmos_get_timeval() (bx_devices.pluginCmosDevice->get_timeval()) - -///////// keyboard macros -#define DEV_mouse_motion(dx, dy, state) \ - (bx_devices.pluginKeyboard->mouse_motion(dx, dy, state)) -#define DEV_kbd_gen_scancode(key) \ - (bx_devices.pluginKeyboard->gen_scancode(key)) -#define DEV_kbd_paste_bytes(bytes, count) \ - (bx_devices.pluginKeyboard->paste_bytes(bytes,count)) -#define DEV_kbd_paste_delay_changed() \ - (bx_devices.pluginKeyboard->paste_delay_changed()) -#define DEV_mouse_enabled_changed(val) \ - (bx_devices.pluginKeyboard->mouse_enabled_changed(val)) - -///////// hard drive macros -#define DEV_hd_read_handler(a, b, c) \ - (bx_devices.pluginHardDrive->virt_read_handler(b, c)) -#define DEV_hd_write_handler(a, b, c, d) \ - (bx_devices.pluginHardDrive->virt_write_handler(b, c, d)) -#define DEV_hd_get_first_cd_handle() \ - (bx_devices.pluginHardDrive->get_first_cd_handle()) -#define DEV_hd_get_device_handle(a,b) \ - (bx_devices.pluginHardDrive->get_device_handle(a,b)) -#define DEV_hd_get_cd_media_status(handle) \ - (bx_devices.pluginHardDrive->get_cd_media_status(handle)) -#define DEV_hd_set_cd_media_status(handle, status) \ - (bx_devices.pluginHardDrive->set_cd_media_status(handle, status)) -#define DEV_hd_close_harddrive() bx_devices.pluginHardDrive->close_harddrive() -#define DEV_hd_present() (bx_devices.pluginHardDrive != &bx_devices.stubHardDrive) - -#define DEV_bulk_io_quantum_requested() (bx_devices.bulkIOQuantumsRequested) -#define DEV_bulk_io_quantum_transferred() (bx_devices.bulkIOQuantumsTransferred) -#define DEV_bulk_io_host_addr() (bx_devices.bulkIOHostAddr) - -///////// FLOPPY macros -#define DEV_floppy_get_media_status(drive) bx_devices.pluginFloppyDevice->get_media_status(drive) -#define DEV_floppy_set_media_status(drive, status) bx_devices.pluginFloppyDevice->set_media_status(drive, status) -#define DEV_floppy_present() (bx_devices.pluginFloppyDevice != &bx_devices.stubFloppy) - -///////// DMA macros -#define DEV_dma_register_8bit_channel(channel, dmaRead, dmaWrite, name) \ - (bx_devices.pluginDmaDevice->registerDMA8Channel(channel, dmaRead, dmaWrite, name)) -#define DEV_dma_register_16bit_channel(channel, dmaRead, dmaWrite, name) \ - (bx_devices.pluginDmaDevice->registerDMA16Channel(channel, dmaRead, dmaWrite, name)) -#define DEV_dma_unregister_channel(channel) \ - (bx_devices.pluginDmaDevice->unregisterDMAChannel(channel)) -#define DEV_dma_set_drq(channel, val) \ - (bx_devices.pluginDmaDevice->set_DRQ(channel, val)) -#define DEV_dma_get_tc() \ - (bx_devices.pluginDmaDevice->get_TC()) -#define DEV_dma_raise_hlda() \ - (bx_devices.pluginDmaDevice->raise_HLDA()) - -///////// PIC macros -#define DEV_pic_lower_irq(b) (bx_devices.pluginPicDevice->lower_irq(b)) -#define DEV_pic_raise_irq(b) (bx_devices.pluginPicDevice->raise_irq(b)) -#define DEV_pic_iac() (bx_devices.pluginPicDevice->IAC()) -#define DEV_pic_show_pic_state() (bx_devices.pluginPicDevice->show_pic_state()) - -///////// VGA macros -#define DEV_vga_mem_read(addr) (bx_devices.pluginVgaDevice->mem_read(addr)) -#define DEV_vga_mem_write(addr, val) (bx_devices.pluginVgaDevice->mem_write(addr, val)) -#define DEV_vga_redraw_area(left, top, right, bottom) \ - (bx_devices.pluginVgaDevice->redraw_area(left, top, right, bottom)) -#define DEV_vga_get_text_snapshot(rawsnap, height, width) \ - (bx_devices.pluginVgaDevice->get_text_snapshot(rawsnap, height, width)) -#define DEV_vga_refresh() \ - (bx_devices.pluginVgaDevice->trigger_timer(bx_devices.pluginVgaDevice)) -#define DEV_vga_set_update_interval(val) \ - (bx_devices.pluginVgaDevice->set_update_interval(val)) -#define DEV_vga_get_actl_pal_idx(index) (bx_devices.pluginVgaDevice->get_actl_palette_idx(index)) - -///////// PCI macros -#define DEV_register_pci_handlers(b,c,d,e,f) \ - (bx_devices.pluginPciBridge->register_pci_handlers(b,c,d,e,f)) -#define DEV_pci_rd_memtype(addr) bx_devices.pluginPciBridge->rd_memType(addr) -#define DEV_pci_wr_memtype(addr) bx_devices.pluginPciBridge->wr_memType(addr) -#define DEV_pci_print_i440fx_state() bx_devices.pluginPciBridge->print_i440fx_state() - -///////// NE2000 macro -#define DEV_ne2k_print_info(file,page,reg,brief) \ - bx_devices.pluginNE2kDevice->print_info(file,page,reg,brief) - - -#if BX_HAVE_DLFCN_H -#include -#endif - -typedef Bit32u (*ioReadHandler_t)(void *, Bit32u, unsigned); -typedef void (*ioWriteHandler_t)(void *, Bit32u, Bit32u, unsigned); - -extern plugin_t *plugins; - -typedef struct _device_t -{ - const char *name; - plugin_t *plugin; - void (*device_init_mem)(BX_MEM_C *); - void (*device_init_dev)(); - void (*device_reset)(unsigned); - void (*device_load_state)(); - void (*device_save_state)(); - - int use_devmodel_interface; // BBD hack - class bx_devmodel_c *devmodel; // BBD hack - - struct _device_t *next; -} device_t; - - -extern device_t *devices; - -void plugin_startup (void); -void plugin_load (char *name, char *args, plugintype_t); -plugin_t *plugin_unload (plugin_t *plugin); -void plugin_init_all (void); -void plugin_fini_all (void); - -/* === Device Stuff === */ -typedef void (*deviceInitMem_t)(BX_MEM_C *); -typedef void (*deviceInitDev_t)(void); -typedef void (*deviceReset_t)(unsigned); -typedef void (*deviceLoad_t)(void); -typedef void (*deviceSave_t)(void); - -BOCHSAPI void pluginRegisterDeviceDevmodel(plugin_t *plugin, plugintype_t type, bx_devmodel_c *dev, char *name); -BOCHSAPI bx_bool pluginDevicePresent(char *name); - -/* === IO port stuff === */ -BOCHSAPI extern int (*pluginRegisterIOReadHandler)(void *thisPtr, ioReadHandler_t callback, - unsigned base, const char *name, Bit8u mask); -BOCHSAPI extern int (*pluginRegisterIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback, - unsigned base, const char *name, Bit8u mask); -BOCHSAPI extern int (*pluginRegisterDefaultIOReadHandler)(void *thisPtr, ioReadHandler_t callback, - const char *name, Bit8u mask); -BOCHSAPI extern int (*pluginRegisterDefaultIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback, - const char *name, Bit8u mask); - -/* === A20 enable line stuff === */ -BOCHSAPI extern unsigned (*pluginGetA20E)(void); -BOCHSAPI extern void (*pluginSetA20E)(unsigned val); - -/* === IRQ stuff === */ -BOCHSAPI extern void (*pluginRegisterIRQ)(unsigned irq, const char *name); -BOCHSAPI extern void (*pluginUnregisterIRQ)(unsigned irq, const char *name); - -/* === Floppy stuff ===*/ -BOCHSAPI extern unsigned (* pluginFloppyGetMediaStatus)(unsigned drive); -BOCHSAPI extern unsigned (* pluginFloppySetMediaStatus)(unsigned drive, unsigned status); - -/* === VGA stuff === */ -BOCHSAPI extern void (* pluginVGARedrawArea)(unsigned x0, unsigned y0, - unsigned width, unsigned height); -BOCHSAPI extern Bit8u (* pluginVGAMemRead)(Bit32u addr); -BOCHSAPI extern void (* pluginVGAMemWrite)(Bit32u addr, Bit8u value); -BOCHSAPI extern void (* pluginVGAGetTextSnapshot)(Bit8u **text_snapshot, - unsigned *txHeight, unsigned *txWidth); -BOCHSAPI extern void (* pluginVGARefresh)(void *); -BOCHSAPI extern void (* pluginVGASetUpdateInterval)(unsigned); -BOCHSAPI extern Bit8u (* pluginVGAGetActlPaletteIdx)(Bit8u index); - -/* === Timer stuff === */ -BOCHSAPI extern int (*pluginRegisterTimer)(void *this_ptr, void (*funct)(void *), - Bit32u useconds, bx_bool continuous, - bx_bool active, const char *name); - -BOCHSAPI extern void (*pluginActivateTimer)(unsigned id, Bit32u usec, bx_bool continuous); -BOCHSAPI extern void (*pluginDeactivateTimer)(unsigned id); - -/* === HRQ stuff === */ -BOCHSAPI extern void (*pluginSetHRQ)(unsigned val); -BOCHSAPI extern void (*pluginSetHRQHackCallback)( void (*callback)(void) ); - -/* === Reset stuff === */ -BOCHSAPI extern void (*pluginResetSignal)(unsigned sig); - -/* === PCI stuff === */ -BOCHSAPI extern bx_bool (*pluginRegisterPCIDevice)(void *this_ptr, - Bit32u (*bx_pci_read_handler)(void *, Bit8u, unsigned), - void(*bx_pci_write_handler)(void *, Bit8u, Bit32u, unsigned), - Bit8u devfunc, const char *name); -BOCHSAPI extern Bit8u (*pluginRd_memType)(Bit32u addr); -BOCHSAPI extern Bit8u (*pluginWr_memType)(Bit32u addr); - -void plugin_abort (void); - -int bx_load_plugin (const char *name, plugintype_t type); -extern void bx_init_plugins (void); -extern void bx_reset_plugins (unsigned); - -// every plugin must define these, within the extern"C" block, so that -// a non-mangled function symbol is available in the shared library. -void plugin_fini(void); -int plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]); - -// still in extern "C" -#define DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(mod) \ - int lib##mod##_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]); \ - void lib##mod##_LTX_plugin_fini(void); - -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(harddrv) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(keyboard) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(serial) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(unmapped) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(biosdev) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(cmos) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(dma) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pic) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(vga) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(floppy) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(parallel) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pci) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pci2isa) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pcivga) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pciusb) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(sb16) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(ne2k) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(extfpuirq) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(gameport) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(amigaos) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(beos) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(carbon) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(macintosh) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(nogui) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(rfb) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(sdl) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(svga) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(term) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(win32) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(wx) -DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(x) - - -#ifdef __cplusplus -} -#endif - -#endif /* __PLUGIN_H */ diff --git a/tools/ioemu/include/state_file.h b/tools/ioemu/include/state_file.h deleted file mode 100644 index 7cef477043..0000000000 --- a/tools/ioemu/include/state_file.h +++ /dev/null @@ -1,61 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: state_file.h,v 1.5 2002/10/24 21:05:00 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -// Classes for helping to make checkpoints of the emulator state. - -#ifndef _STATE_FILE_H -#define _STATE_FILE_H -#include -#include - - -class BOCHSAPI state_file { - void init(void); -public: - FILE *file; - class logfunctions *log; - - FILE *get_handle(); - void write(Bit8u); - void write(Bit16u); - void write(Bit32u); - void write(Bit64u); - void write(const void*, size_t); - void read(Bit8u &); - void read(Bit16u &); - void read(Bit32u &); - void read(Bit64u &); - void read(void *, size_t); - void write_check(const char *); - void read_check (const char *); - - state_file (const char *name, const char *options); - state_file (FILE *f); - ~state_file(); -}; - -#endif // #ifndef _STATE_FILE_H diff --git a/tools/ioemu/iodev/Makefile b/tools/ioemu/iodev/Makefile deleted file mode 100644 index e56e3862cf..0000000000 --- a/tools/ioemu/iodev/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -XEN_ROOT= ../../../ -include $(XEN_ROOT)/tools/Rules.mk - -TOPDIR= .. -CXXFLAGS=-I. -I../include -I.. - -ifeq ($(XEN_TARGET_ARCH), x86_32) -CXXFLAGS+=-D_FILE_OFFSET_BITS=64 -endif - -OBJS=$(patsubst %.cc,%.o,$(wildcard *.cc)) -BXLIBS = ../gui/libgui.a ../memory/libmemory.a -LDLIBS= $(BXLIBS) $(X11_LDPATH) -lX11 -lXpm -lstdc++ -L../../../tools/libxc -L../../../tools/libxutil -lxc -lxutil -lpthread -lncurses - -all: device-model - -device-model: $(OBJS) $(BXLIBS) - $(CC) $(LDFLAGS) $(OBJS) $(LOADLIBES) $(LDLIBS) -o $@ - -include $(TOPDIR)/mk/helix.mk - -install:: all - install device-model $(DESTDIR)/usr/sbin diff --git a/tools/ioemu/iodev/aspi-win32.h b/tools/ioemu/iodev/aspi-win32.h deleted file mode 100644 index afa62d1e19..0000000000 --- a/tools/ioemu/iodev/aspi-win32.h +++ /dev/null @@ -1,210 +0,0 @@ -// -// iodev/aspi-win32.h -// $Id: aspi-win32.h,v 1.2 2001/06/25 12:52:37 bdenney Exp $ -// -// This file was copied from cdrecord 1.9 under libscg/scg/aspi-win32.h. -// The only modification is related to use of the PACKED keyword. -// - -#ifndef __ASPI_WIN32_H_ -#define __ASPI_WIN32_H_ - -#include - -#ifndef PACKED -// It seems that VC++ has no PACKED keyword but Cygwin does. We can just -// define PACKED to be empty if it's not already defined by the system -// headers. -#define PACKED /* empty */ -#endif - -/*************************************************************************** - ** SCSI MISCELLANEOUS EQUATES - ***************************************************************************/ -#define SENSE_LEN 14 /* Default sense buffer length */ -#define SRB_DIR_SCSI 0x00 /* Direction determined by SCSI */ -#define SRB_POSTING 0x01 /* Enable ASPI posting */ -#define SRB_ENABLE_RESIDUAL_COUNT 0x04 /* Enable residual byte count */ - /* reporting */ -#define SRB_DIR_IN 0x08 /* Transfer from SCSI target to */ - /* host */ -#define SRB_DIR_OUT 0x10 /* Transfer from host to SCSI */ - /* target */ -#define SRB_EVENT_NOTIFY 0x40 /* Enable ASPI event notification */ -#define RESIDUAL_COUNT_SUPPORTED 0x02 /* Extended buffer flag */ -#define MAX_SRB_TIMEOUT 1080001u /* 30 hour maximum timeout in sec */ -#define DEFAULT_SRB_TIMEOUT 1080001u /* use max.timeout by default */ - -/*************************************************************************** - ** ASPI command definitions - ***************************************************************************/ -#define SC_HA_INQUIRY 0x00 /* Host adapter inquiry */ -#define SC_GET_DEV_TYPE 0x01 /* Get device type */ -#define SC_EXEC_SCSI_CMD 0x02 /* Execute SCSI command */ -#define SC_ABORT_SRB 0x03 /* Abort an SRB */ -#define SC_RESET_DEV 0x04 /* SCSI bus device reset */ -#define SC_SET_HA_PARMS 0x05 /* Set HA parameters */ -#define SC_GET_DISK_INFO 0x06 /* Get Disk */ -#define SC_RESCAN_SCSI_BUS 0x07 /* Rebuild SCSI device map */ -#define SC_GETSET_TIMEOUTS 0x08 /* Get/Set target timeouts */ - - -/*************************************************************************** - ** SRB Status - ***************************************************************************/ -#define SS_PENDING 0x00 /* SRB being processed */ -#define SS_COMP 0x01 /* SRB completed without error */ -#define SS_ABORTED 0x02 /* SRB aborted */ -#define SS_ABORT_FAIL 0x03 /* Unable to abort SRB */ -#define SS_ERR 0x04 /* SRB completed with error */ -#define SS_INVALID_CMD 0x80 /* Invalid ASPI command */ -#define SS_INVALID_HA 0x81 /* Invalid host adapter number */ -#define SS_NO_DEVICE 0x82 /* SCSI device not installed */ -#define SS_INVALID_SRB 0xE0 /* Invalid parameter set in SRB */ -#define SS_OLD_MANAGER 0xE1 /* ASPI manager doesn't support */ - /* windows */ -#define SS_BUFFER_ALIGN 0xE1 /* Buffer not aligned (replaces */ - /* SS_OLD_MANAGER in Win32) */ -#define SS_ILLEGAL_MODE 0xE2 /* Unsupported Windows mode */ -#define SS_NO_ASPI 0xE3 /* No ASPI managers */ -#define SS_FAILED_INIT 0xE4 /* ASPI for windows failed init */ -#define SS_ASPI_IS_BUSY 0xE5 /* No resources available to */ - /* execute command */ -#define SS_BUFFER_TO_BIG 0xE6 /* Buffer size too big to handle */ -#define SS_BUFFER_TOO_BIG 0xE6 /* Correct spelling of 'too' */ -#define SS_MISMATCHED_COMPONENTS 0xE7 /* The DLLs/EXEs of ASPI don't */ - /* version check */ -#define SS_NO_ADAPTERS 0xE8 /* No host adapters to manager */ -#define SS_INSUFFICIENT_RESOURCES 0xE9 /* Couldn't allocate resources */ - /* needed to init */ -#define SS_ASPI_IS_SHUTDOWN 0xEA /* Call came to ASPI after */ - /* PROCESS_DETACH */ -#define SS_BAD_INSTALL 0xEB /* The DLL or other components */ - /* are installed wrong */ - -/*************************************************************************** - ** Host Adapter Status - ***************************************************************************/ -#define HASTAT_OK 0x00 /* No error detected by HA */ -#define HASTAT_SEL_TO 0x11 /* Selection Timeout */ -#define HASTAT_DO_DU 0x12 /* Data overrun/data underrun */ -#define HASTAT_BUS_FREE 0x13 /* Unexpected bus free */ -#define HASTAT_PHASE_ERR 0x14 /* Target bus phase sequence */ -#define HASTAT_TIMEOUT 0x09 /* Timed out while SRB was */ - /* waiting to be processed */ -#define HASTAT_COMMAND_TIMEOUT 0x0B /* Adapter timed out while */ - /* processing SRB */ -#define HASTAT_MESSAGE_REJECT 0x0D /* While processing the SRB, the */ - /* adapter received a MESSAGE */ -#define HASTAT_BUS_RESET 0x0E /* A bus reset was detected */ -#define HASTAT_PARITY_ERROR 0x0F /* A parity error was detected */ -#define HASTAT_REQUEST_SENSE_FAILED 0x10 /* The adapter failed in issuing */ - -/*************************************************************************** - ** SRB - HOST ADAPTER INQUIRIY - SC_HA_INQUIRY (0) - ***************************************************************************/ -typedef struct { - BYTE SRB_Cmd; /* 00/000 ASPI command code == SC_HA_INQUIRY */ - BYTE SRB_Status; /* 01/001 ASPI command status byte */ - BYTE SRB_HaId; /* 02/002 ASPI host adapter number */ - BYTE SRB_Flags; /* 03/003 ASPI request flags */ - DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */ - BYTE HA_Count; /* 08/008 Number of host adapters present */ - BYTE HA_SCSI_ID; /* 09/009 SCSI ID of host adapter */ - BYTE HA_ManagerId[16]; /* 0a/010 String describing the manager */ - BYTE HA_Identifier[16]; /* 1a/026 String describing the host adapter */ - BYTE HA_Unique[16]; /* 2a/042 Host Adapter Unique parameters */ - WORD HA_Rsvd1; /* 3a/058 Reserved, must = 0 */ -} PACKED SRB_HAInquiry, *PSRB_HAInquiry, FAR *LPSRB_HAInquiry; - - -/*************************************************************************** - ** SRB - GET DEVICE TYPE - SC_GET_DEV_TYPE (1) - ***************************************************************************/ -typedef struct -{ - BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_GET_DEV_TYPE */ - BYTE SRB_Status; /* 01/001 ASPI command status byte */ - BYTE SRB_HaId; /* 02/002 ASPI host adapter number */ - BYTE SRB_Flags; /* 03/003 Reserved, must = 0 */ - DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */ - BYTE SRB_Target; /* 08/008 Target's SCSI ID */ - BYTE SRB_Lun; /* 09/009 Target's LUN number */ - BYTE SRB_DeviceType; /* 0a/010 Target's peripheral device type */ - BYTE SRB_Rsvd1; /* 0b/011 Reserved, must = 0 */ -} PACKED SRB_GDEVBlock, *PSRB_GDEVBlock, FAR *LPSRB_GDEVBlock; - - -/*************************************************************************** - ** SRB - EXECUTE SCSI COMMAND - SC_EXEC_SCSI_CMD (2) - ***************************************************************************/ -typedef struct -{ - BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_EXEC_SCSI_CMD */ - BYTE SRB_Status; /* 01/001 ASPI command status byte */ - BYTE SRB_HaId; /* 02/002 ASPI host adapter number */ - BYTE SRB_Flags; /* 03/003 Reserved, must = 0 */ - DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */ - BYTE SRB_Target; /* 08/008 Target's SCSI ID */ - BYTE SRB_Lun; /* 09/009 Target's LUN */ - WORD SRB_Rsvd1; /* 0a/010 Reserved for alignment */ - DWORD SRB_BufLen; /* 0c/012 Data Allocation Length */ - BYTE FAR *SRB_BufPointer; /* 10/016 Data Buffer Pointer */ - BYTE SRB_SenseLen; /* 14/020 Sense Allocation Length */ - BYTE SRB_CDBLen; /* 15/021 CDB Length */ - BYTE SRB_HaStat; /* 16/022 Host Adapter Status */ - BYTE SRB_TargStat; /* 17/023 Target Status */ - VOID FAR *SRB_PostProc; /* 18/024 Post routine */ - BYTE SRB_Rsvd2[20]; /* 1c/028 Reserved, must = 0 */ - BYTE CDBByte[16]; /* 30/048 SCSI CDB */ - BYTE SenseArea[SENSE_LEN+2]; /* 40/064 Request Sense buffer */ -} PACKED SRB_ExecSCSICmd, *PSRB_ExecSCSICmd, FAR *LPSRB_ExecSCSICmd; - - -typedef struct -{ - BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_ABORT_SRB */ - BYTE SRB_Status; /* 01/001 ASPI command status byte */ - BYTE SRB_HaId; /* 02/002 ASPI host adapter number */ - BYTE SRB_Flags; /* 03/003 Reserved, must = 0 */ - DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */ - void *SRB_ToAbort; /* 08/008 Pointer to SRB to abort */ -} PACKED SRB_Abort, *PSRB_Abort, FAR *LPSRB_Abort; - - -/*************************************************************************** - ** SRB - BUS DEVICE RESET - SC_RESET_DEV (4) - ***************************************************************************/ -typedef struct -{ - BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_RESET_DEV */ - BYTE SRB_Status; /* 01/001 ASPI command status byte */ - BYTE SRB_HaId; /* 02/002 ASPI host adapter number */ - DWORD SRB_Flags; /* 04/004 Reserved */ - BYTE SRB_Target; /* 08/008 Target's SCSI ID */ - BYTE SRB_Lun; /* 09/009 Target's LUN number */ - BYTE SRB_Rsvd1[12]; /* 0A/010 Reserved for alignment */ - BYTE SRB_HaStat; /* 16/022 Host Adapter Status */ - BYTE SRB_TargStat; /* 17/023 Target Status */ - VOID FAR *SRB_PostProc; /* 18/024 Post routine */ - BYTE SRB_Rsvd2[36]; /* 1C/028 Reserved, must = 0 */ -} SRB_BusDeviceReset, *PSRB_BusDeviceReset, FAR *LPSRB_BusDeviceReset; - -typedef struct tag_ASPI32BUFF -{ - PBYTE AB_BufPointer; - DWORD AB_BufLen; - DWORD AB_ZeroFill; - DWORD AB_Reserved; -} PACKED ASPI32BUFF, *PASPI32BUFF, FAR *LPASPI32BUFF; - -typedef struct -{ - BYTE SRB_Cmd; - BYTE SRB_Status; - BYTE SRB_HaId; - BYTE SRB_Flags; - DWORD SRB_Hdr_Rsvd; -} SRB, *PSRB, FAR *LPSRB; - -#endif diff --git a/tools/ioemu/iodev/biosdev.cc b/tools/ioemu/iodev/biosdev.cc deleted file mode 100644 index d4a6ef2b8c..0000000000 --- a/tools/ioemu/iodev/biosdev.cc +++ /dev/null @@ -1,212 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: biosdev.cc,v 1.7 2003/12/08 19:36:23 danielg4 Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -// Here are the virtual ports use to display messages from the bioses : -// -// 0x0400 : rombios Panic port with message -// 0x0401 : rombios Panic port with line number -// 0x0402 : rombios Info port with message -// 0x0403 : rombios Debug port with message -// -// 0x0500 : vgabios Info port with message -// 0x0501 : vgabios Panic port with message -// 0x0502 : vgabios Panic port with line number -// 0x0503 : vgabios Debug port with message - - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" - -bx_biosdev_c *theBiosDevice; - - int -libbiosdev_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - theBiosDevice = new bx_biosdev_c (); - bx_devices.pluginBiosDevice = theBiosDevice; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theBiosDevice, BX_PLUGIN_BIOSDEV); - return(0); // Success -} - - void -libbiosdev_LTX_plugin_fini(void) -{ -} - -logfunctions *bioslog; -logfunctions *vgabioslog; - -bx_biosdev_c::bx_biosdev_c(void) -{ - bioslog = new logfunctions(); - bioslog->put("BIOS"); - bioslog->settype(BIOSLOG); - s.bios_message_i = 0; - - vgabioslog = new logfunctions(); - vgabioslog->put("VBIOS"); - vgabioslog->settype(BIOSLOG); - s.vgabios_message_i = 0; -} - -bx_biosdev_c::~bx_biosdev_c(void) -{ - if ( bioslog != NULL ) - { - delete bioslog; - bioslog = NULL; - } - - if ( vgabioslog != NULL ) - { - delete vgabioslog; - vgabioslog = NULL; - } -} - - void -bx_biosdev_c::init(void) -{ - DEV_register_iowrite_handler(this, write_handler, 0x0400, "Bios Panic Port 1", 3); - DEV_register_iowrite_handler(this, write_handler, 0x0401, "Bios Panic Port 2", 3); - DEV_register_iowrite_handler(this, write_handler, 0x0403, "Bios Debug Port", 1); - DEV_register_iowrite_handler(this, write_handler, 0x0402, "Bios Info Port", 1); - - DEV_register_iowrite_handler(this, write_handler, 0x0501, "VGABios Panic Port 1", 3); - DEV_register_iowrite_handler(this, write_handler, 0x0502, "VGABios Panic Port 2", 3); - DEV_register_iowrite_handler(this, write_handler, 0x0503, "VGABios Debug Port", 1); - DEV_register_iowrite_handler(this, write_handler, 0x0500, "VGABios Info Port", 1); -} - - void -bx_biosdev_c::reset(unsigned type) -{ -} - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_biosdev_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_BIOS_SMF - bx_biosdev_c *class_ptr = (bx_biosdev_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - - void -bx_biosdev_c::write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_BIOS_SMF - UNUSED(io_len); - - - switch (address) { - // 0x400-0x401 are used as panic ports for the rombios - case 0x0401: - if (BX_BIOS_THIS s.bios_message_i > 0) { - // if there are bits of message in the buffer, print them as the - // panic message. Otherwise fall into the next case. - if (BX_BIOS_THIS s.bios_message_i >= BX_BIOS_MESSAGE_SIZE) - BX_BIOS_THIS s.bios_message_i = BX_BIOS_MESSAGE_SIZE-1; - BX_BIOS_THIS s.bios_message[ BX_BIOS_THIS s.bios_message_i] = 0; - BX_BIOS_THIS s.bios_message_i = 0; - bioslog->panic("%s", BX_BIOS_THIS s.bios_message); - break; - } - case 0x0400: - bioslog->panic("BIOS panic at rombios.c, line %d", value); - break; - - // 0x0402 is used as the info port for the rombios - // 0x0403 is used as the debug port for the rombios - case 0x0402: - case 0x0403: - BX_BIOS_THIS s.bios_message[BX_BIOS_THIS s.bios_message_i] = - (Bit8u) value; - BX_BIOS_THIS s.bios_message_i ++; - if ( BX_BIOS_THIS s.bios_message_i >= BX_BIOS_MESSAGE_SIZE ) { - BX_BIOS_THIS s.bios_message[ BX_BIOS_MESSAGE_SIZE - 1] = 0; - BX_BIOS_THIS s.bios_message_i = 0; - if (address==0x403) bioslog->ldebug("%s", BX_BIOS_THIS s.bios_message); - else bioslog->info("%s", BX_BIOS_THIS s.bios_message); - } - else if ((value & 0xff) == '\n') { - BX_BIOS_THIS s.bios_message[ BX_BIOS_THIS s.bios_message_i - 1 ] = 0; - BX_BIOS_THIS s.bios_message_i = 0; - if (address==0x403) bioslog->ldebug("%s", BX_BIOS_THIS s.bios_message); - else bioslog->info("%s", BX_BIOS_THIS s.bios_message); - } - break; - - // 0x501-0x502 are used as panic ports for the vgabios - case 0x0502: - if (BX_BIOS_THIS s.vgabios_message_i > 0) { - // if there are bits of message in the buffer, print them as the - // panic message. Otherwise fall into the next case. - if (BX_BIOS_THIS s.vgabios_message_i >= BX_BIOS_MESSAGE_SIZE) - BX_BIOS_THIS s.vgabios_message_i = BX_BIOS_MESSAGE_SIZE-1; - BX_BIOS_THIS s.vgabios_message[ BX_BIOS_THIS s.vgabios_message_i] = 0; - BX_BIOS_THIS s.vgabios_message_i = 0; - vgabioslog->panic("%s", BX_BIOS_THIS s.vgabios_message); - break; - } - case 0x0501: - vgabioslog->panic("BIOS panic at rombios.c, line %d", value); - break; - - // 0x0500 is used as the message port for the vgabios - case 0x0500: - case 0x0503: - BX_BIOS_THIS s.vgabios_message[BX_BIOS_THIS s.vgabios_message_i] = - (Bit8u) value; - BX_BIOS_THIS s.vgabios_message_i ++; - if ( BX_BIOS_THIS s.vgabios_message_i >= BX_BIOS_MESSAGE_SIZE ) { - BX_BIOS_THIS s.vgabios_message[ BX_BIOS_MESSAGE_SIZE - 1] = 0; - BX_BIOS_THIS s.vgabios_message_i = 0; - if (address==0x503) vgabioslog->ldebug("%s", BX_BIOS_THIS s.vgabios_message); - else vgabioslog->info("%s", BX_BIOS_THIS s.vgabios_message); - } - else if ((value & 0xff) == '\n') { - BX_BIOS_THIS s.vgabios_message[ BX_BIOS_THIS s.vgabios_message_i - 1 ] = 0; - BX_BIOS_THIS s.vgabios_message_i = 0; - if (address==0x503) vgabioslog->ldebug("%s", BX_BIOS_THIS s.vgabios_message); - else vgabioslog->info("%s", BX_BIOS_THIS s.vgabios_message); - } - break; - - default: - break; - } -} diff --git a/tools/ioemu/iodev/biosdev.h b/tools/ioemu/iodev/biosdev.h deleted file mode 100644 index 7cd98736f4..0000000000 --- a/tools/ioemu/iodev/biosdev.h +++ /dev/null @@ -1,63 +0,0 @@ - -// $Id: biosdev.h,v 1.3 2002/10/24 21:07:09 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -#define BX_BIOS_MESSAGE_SIZE 80 - - -#if BX_USE_BIOS_SMF -# define BX_BIOS_SMF static -# define BX_BIOS_THIS theBiosDevice-> -#else -# define BX_BIOS_SMF -# define BX_BIOS_THIS this-> -#endif - - -class bx_biosdev_c : public bx_devmodel_c { -public: - bx_biosdev_c(void); - ~bx_biosdev_c(void); - - virtual void init(void); - virtual void reset (unsigned type); - -private: - - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); -#if !BX_USE_BIOS_SMF - void write(Bit32u address, Bit32u value, unsigned io_len); -#endif - - struct { - Bit8u bios_message[BX_BIOS_MESSAGE_SIZE]; - unsigned int bios_message_i; - - Bit8u vgabios_message[BX_BIOS_MESSAGE_SIZE]; - unsigned int vgabios_message_i; - } s; // state information - - }; diff --git a/tools/ioemu/iodev/cdrom.cc b/tools/ioemu/iodev/cdrom.cc deleted file mode 100644 index 2b78e8d15a..0000000000 --- a/tools/ioemu/iodev/cdrom.cc +++ /dev/null @@ -1,1338 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: cdrom.cc,v 1.66 2003/12/08 23:49:48 danielg4 Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -// These are the low-level CDROM functions which are called -// from 'harddrv.cc'. They effect the OS specific functionality -// needed by the CDROM emulation in 'harddrv.cc'. Mostly, just -// ioctl() calls and such. Should be fairly easy to add support -// for your OS if it is not supported yet. - - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_SUPPORT_CDROM - -#define LOG_THIS /* no SMF tricks here, not needed */ - -extern "C" { -#include -} - -#ifdef __linux__ -extern "C" { -#include -#include -// I use the framesize in non OS specific code too -#define BX_CD_FRAMESIZE CD_FRAMESIZE -} - -#elif defined(__GNU__) || (defined(__CYGWIN32__) && !defined(WIN32)) -extern "C" { -#include -#define BX_CD_FRAMESIZE 2048 -#define CD_FRAMESIZE 2048 -} - -#elif BX_WITH_MACOS -#define BX_CD_FRAMESIZE 2048 -#define CD_FRAMESIZE 2048 - -#elif defined(__sun) -extern "C" { -#include -#include -#include -#include -#define BX_CD_FRAMESIZE CDROM_BLK_2048 -} - -#elif defined(__DJGPP__) -extern "C" { -#include -#define BX_CD_FRAMESIZE 2048 -#define CD_FRAMESIZE 2048 -} - -#elif defined(__BEOS__) -#include "cdrom_beos.h" -#define BX_CD_FRAMESIZE 2048 - -#elif (defined (__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)) -// OpenBSD pre version 2.7 may require extern "C" { } structure around -// all the includes, because the i386 sys/disklabel.h contains code which -// c++ considers invalid. -#include -#include -#include -#include -#include -#include -// ntohl(x) et al have been moved out of sys/param.h in FreeBSD 5 -#include - -// XXX -#define BX_CD_FRAMESIZE 2048 -#define CD_FRAMESIZE 2048 - -#elif defined(__APPLE__) -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -// These definitions were taken from mount_cd9660.c -// There are some similar definitions in IOCDTypes.h -// however there seems to be some dissagreement in -// the definition of CDTOC.length -struct _CDMSF { - u_char minute; - u_char second; - u_char frame; -}; - -#define MSF_TO_LBA(msf) \ - (((((msf).minute * 60UL) + (msf).second) * 75UL) + (msf).frame - 150) - -struct _CDTOC_Desc { - u_char session; - u_char ctrl_adr; /* typed to be machine and compiler independent */ - u_char tno; - u_char point; - struct _CDMSF address; - u_char zero; - struct _CDMSF p; -}; - -struct _CDTOC { - u_short length; /* in native cpu endian */ - u_char first_session; - u_char last_session; - struct _CDTOC_Desc trackdesc[1]; -}; - -static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator, mach_port_t *masterPort ); -static kern_return_t GetDeviceFilePath( io_iterator_t mediaIterator, char *deviceFilePath, CFIndex maxPathSize ); -//int OpenDrive( const char *deviceFilePath ); -static struct _CDTOC * ReadTOC( const char * devpath ); - -static char CDDevicePath[ MAXPATHLEN ]; - -#define BX_CD_FRAMESIZE 2048 -#define CD_FRAMESIZE 2048 - -#elif defined(WIN32) -// windows.h included by bochs.h -#include -#include "aspi-win32.h" -#include "scsidefs.h" - -DWORD (*GetASPI32SupportInfo)(void); -DWORD (*SendASPI32Command)(LPSRB); -BOOL (*GetASPI32Buffer)(PASPI32BUFF); -BOOL (*FreeASPI32Buffer)(PASPI32BUFF); -BOOL (*TranslateASPI32Address)(PDWORD,PDWORD); -DWORD (*GetASPI32DLLVersion)(void); - - -static BOOL bUseASPI = FALSE; -static BOOL bHaveDev; -static UINT cdromCount = 0; -static HINSTANCE hASPI = NULL; - -#define BX_CD_FRAMESIZE 2048 -#define CD_FRAMESIZE 2048 - -#else // all others (Irix, Tru64) -#include -#include -#include -#define BX_CD_FRAMESIZE 2048 -#define CD_FRAMESIZE 2048 -#endif - -#include - -#ifdef __APPLE__ -static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator, - mach_port_t *masterPort ) -{ - kern_return_t kernResult; - CFMutableDictionaryRef classesToMatch; - kernResult = IOMasterPort( bootstrap_port, masterPort ); - if ( kernResult != KERN_SUCCESS ) - { - fprintf ( stderr, "IOMasterPort returned %d\n", kernResult ); - return kernResult; - } - // CD media are instances of class kIOCDMediaClass. - classesToMatch = IOServiceMatching( kIOCDMediaClass ); - if ( classesToMatch == NULL ) - fprintf ( stderr, "IOServiceMatching returned a NULL dictionary.\n" ); - else - { - // Each IOMedia object has a property with key kIOMediaEjectableKey - // which is true if the media is indeed ejectable. So add property - // to CFDictionary for matching. - CFDictionarySetValue( classesToMatch, - CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue ); - } - kernResult = IOServiceGetMatchingServices( *masterPort, - classesToMatch, mediaIterator ); - if ( (kernResult != KERN_SUCCESS) || (*mediaIterator == NULL) ) - fprintf( stderr, "No ejectable CD media found.\n kernResult = %d\n", kernResult ); - - return kernResult; -} - - -static kern_return_t GetDeviceFilePath( io_iterator_t mediaIterator, - char *deviceFilePath, CFIndex maxPathSize ) -{ - io_object_t nextMedia; - kern_return_t kernResult = KERN_FAILURE; - nextMedia = IOIteratorNext( mediaIterator ); - if ( nextMedia == NULL ) - { - *deviceFilePath = '\0'; - } - else - { - CFTypeRef deviceFilePathAsCFString; - deviceFilePathAsCFString = IORegistryEntryCreateCFProperty( - nextMedia, CFSTR( kIOBSDNameKey ), - kCFAllocatorDefault, 0 ); - *deviceFilePath = '\0'; - if ( deviceFilePathAsCFString ) - { - size_t devPathLength = strlen( _PATH_DEV ); - strcpy( deviceFilePath, _PATH_DEV ); - if ( CFStringGetCString( (const __CFString *) deviceFilePathAsCFString, - deviceFilePath + devPathLength, - maxPathSize - devPathLength, - kCFStringEncodingASCII ) ) - { - // fprintf( stderr, "BSD path: %s\n", deviceFilePath ); - kernResult = KERN_SUCCESS; - } - CFRelease( deviceFilePathAsCFString ); - } - } - IOObjectRelease( nextMedia ); - return kernResult; -} - - -static int OpenDrive( const char *deviceFilePath ) -{ - - int fileDescriptor; - - fileDescriptor = open( deviceFilePath, O_RDONLY ); - if ( fileDescriptor == -1 ) - fprintf( stderr, "Error %d opening device %s.\n", errno, deviceFilePath ); - return fileDescriptor; - -} - -static struct _CDTOC * ReadTOC( const char * devpath ) { - - struct _CDTOC * toc_p = NULL; - io_iterator_t iterator = 0; - io_registry_entry_t service = 0; - CFDictionaryRef properties = 0; - CFDataRef data = 0; - mach_port_t port = 0; - char * devname; - - if (( devname = strrchr( devpath, '/' )) != NULL ) { - ++devname; - } - else { - devname = (char *) devpath; - } - - if ( IOMasterPort(bootstrap_port, &port ) != KERN_SUCCESS ) { - fprintf( stderr, "IOMasterPort failed\n" ); - goto Exit; - } - - if ( IOServiceGetMatchingServices( port, IOBSDNameMatching( port, 0, devname ), - &iterator ) != KERN_SUCCESS ) { - fprintf( stderr, "IOServiceGetMatchingServices failed\n" ); - goto Exit; - } - - service = IOIteratorNext( iterator ); - - IOObjectRelease( iterator ); - - iterator = 0; - - while ( service && !IOObjectConformsTo( service, "IOCDMedia" )) { - if ( IORegistryEntryGetParentIterator( service, kIOServicePlane, - &iterator ) != KERN_SUCCESS ) { - fprintf( stderr, "IORegistryEntryGetParentIterator failed\n" ); - goto Exit; - } - - IOObjectRelease( service ); - service = IOIteratorNext( iterator ); - IOObjectRelease( iterator ); - - } - - if ( service == NULL ) { - fprintf( stderr, "CD media not found\n" ); - goto Exit; - } - - if ( IORegistryEntryCreateCFProperties( service, (__CFDictionary **) &properties, - kCFAllocatorDefault, - kNilOptions ) != KERN_SUCCESS ) { - fprintf( stderr, "IORegistryEntryGetParentIterator failed\n" ); - goto Exit; - } - - data = (CFDataRef) CFDictionaryGetValue( properties, CFSTR(kIOCDMediaTOCKey) ); - if ( data == NULL ) { - fprintf( stderr, "CFDictionaryGetValue failed\n" ); - goto Exit; - } - else { - - CFRange range; - CFIndex buflen; - - buflen = CFDataGetLength( data ) + 1; - range = CFRangeMake( 0, buflen ); - toc_p = (struct _CDTOC *) malloc( buflen ); - if ( toc_p == NULL ) { - fprintf( stderr, "Out of memory\n" ); - goto Exit; - } - else { - CFDataGetBytes( data, range, (unsigned char *) toc_p ); - } - - /* - fprintf( stderr, "Table of contents\n length %d first %d last %d\n", - toc_p->length, toc_p->first_session, toc_p->last_session ); - */ - - CFRelease( properties ); - - } - - - Exit: - - if ( service ) { - IOObjectRelease( service ); - } - - return toc_p; - -} -#endif - -#ifdef WIN32 - -bool ReadCDSector(unsigned int hid, unsigned int tid, unsigned int lun, unsigned long frame, unsigned char *buf, int bufsize) -{ - HANDLE hEventSRB; - SRB_ExecSCSICmd srb; - DWORD dwStatus; - - hEventSRB = CreateEvent(NULL, TRUE, FALSE, NULL); - - memset(&srb,0,sizeof(SRB_ExecSCSICmd)); - srb.SRB_Cmd = SC_EXEC_SCSI_CMD; - srb.SRB_HaId = hid; - srb.SRB_Target = tid; - srb.SRB_Lun = lun; - srb.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - srb.SRB_SenseLen = SENSE_LEN; - srb.SRB_PostProc = hEventSRB; - srb.SRB_BufPointer = buf; - srb.SRB_BufLen = bufsize; - srb.SRB_CDBLen = 10; - srb.CDBByte[0] = SCSI_READ10; - srb.CDBByte[2] = (unsigned char) (frame>>24); - srb.CDBByte[3] = (unsigned char) (frame>>16); - srb.CDBByte[4] = (unsigned char) (frame>>8); - srb.CDBByte[5] = (unsigned char) (frame); - srb.CDBByte[7] = 0; - srb.CDBByte[8] = 1; /* read 1 frames */ - - ResetEvent(hEventSRB); - dwStatus = SendASPI32Command((SRB *)&srb); - if(dwStatus == SS_PENDING) { - WaitForSingleObject(hEventSRB, 100000); - } - CloseHandle(hEventSRB); - return (srb.SRB_TargStat == STATUS_GOOD); -} - -int GetCDCapacity(unsigned int hid, unsigned int tid, unsigned int lun) -{ - HANDLE hEventSRB; - SRB_ExecSCSICmd srb; - DWORD dwStatus; - unsigned char buf[8]; - - hEventSRB = CreateEvent(NULL, TRUE, FALSE, NULL); - - memset(&buf, 0, sizeof(buf)); - memset(&srb,0,sizeof(SRB_ExecSCSICmd)); - srb.SRB_Cmd = SC_EXEC_SCSI_CMD; - srb.SRB_HaId = hid; - srb.SRB_Target = tid; - srb.SRB_Lun = lun; - srb.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; - srb.SRB_SenseLen = SENSE_LEN; - srb.SRB_PostProc = hEventSRB; - srb.SRB_BufPointer = (unsigned char *)buf; - srb.SRB_BufLen = 8; - srb.SRB_CDBLen = 10; - srb.CDBByte[0] = SCSI_READCDCAP; - srb.CDBByte[2] = 0; - srb.CDBByte[3] = 0; - srb.CDBByte[4] = 0; - srb.CDBByte[5] = 0; - srb.CDBByte[8] = 0; - - ResetEvent(hEventSRB); - dwStatus = SendASPI32Command((SRB *)&srb); - if(dwStatus == SS_PENDING) { - WaitForSingleObject(hEventSRB, 100000); - } - - CloseHandle(hEventSRB); - return ((buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3]) * ((buf[4] << 24) + (buf[5] << 16) + (buf[6] << 8) + buf[7]); -} - -#endif - -cdrom_interface::cdrom_interface(char *dev) -{ - put("CD"); - settype(CDLOG); - fd = -1; // File descriptor not yet allocated - - if ( dev == NULL ) - path = NULL; - else { - path = strdup(dev); - } - using_file=0; -} - -void -cdrom_interface::init(void) { - BX_DEBUG(("Init $Id: cdrom.cc,v 1.66 2003/12/08 23:49:48 danielg4 Exp $")); - BX_INFO(("file = '%s'",path)); -} - -cdrom_interface::~cdrom_interface(void) -{ -#ifdef WIN32 -#else - if (fd >= 0) - close(fd); -#endif - if (path) - free(path); - BX_DEBUG(("Exit")); -} - - bx_bool -cdrom_interface::insert_cdrom(char *dev) -{ - unsigned char buffer[BX_CD_FRAMESIZE]; - ssize_t ret; - - // Load CD-ROM. Returns false if CD is not ready. - if (dev != NULL) path = strdup(dev); - BX_INFO (("load cdrom with path=%s", path)); -#ifdef WIN32 - char drive[256]; - OSVERSIONINFO osi; - if ( (path[1] == ':') && (strlen(path) == 2) ) - { - osi.dwOSVersionInfoSize = sizeof(osi); - GetVersionEx(&osi); - if(osi.dwPlatformId == VER_PLATFORM_WIN32_NT) { - // Use direct device access under windows NT/2k - - // With all the backslashes it's hard to see, but to open D: drive - // the name would be: \\.\d: - sprintf(drive, "\\\\.\\%s", path); - using_file = 0; - BX_INFO (("Using direct access for cdrom.")); - // This trick only works for Win2k and WinNT, so warn the user of that. - } else { - BX_INFO(("Using ASPI for cdrom. Drive letters are unused yet.")); - bUseASPI = TRUE; - } - } - else - { - strcpy(drive,path); - using_file = 1; - bUseASPI = FALSE; - BX_INFO (("Opening image file as a cd")); - } - if(bUseASPI) { - DWORD d; - UINT cdr, cnt, max; - UINT i, j, k; - SRB_HAInquiry sh; - SRB_GDEVBlock sd; - if (!hASPI) { - hASPI = LoadLibrary("WNASPI32.DLL"); - } - if(hASPI) { - SendASPI32Command = (DWORD(*)(LPSRB))GetProcAddress( hASPI, "SendASPI32Command" ); - GetASPI32DLLVersion = (DWORD(*)(void))GetProcAddress( hASPI, "GetASPI32DLLVersion" ); - GetASPI32SupportInfo = (DWORD(*)(void))GetProcAddress( hASPI, "GetASPI32SupportInfo" ); -// BX_INFO(("Using first CDROM. Please upgrade your ASPI drivers to version 4.01 or later if you wish to specify a cdrom driver.")); - - cdr = 0; - bHaveDev = FALSE; - d = GetASPI32SupportInfo(); - cnt = LOBYTE(LOWORD(d)); - for(i = 0; i < cnt; i++) { - memset(&sh, 0, sizeof(sh)); - sh.SRB_Cmd = SC_HA_INQUIRY; - sh.SRB_HaId = i; - SendASPI32Command((LPSRB)&sh); - if(sh.SRB_Status != SS_COMP) - continue; - - max = (int)sh.HA_Unique[3]; - for(j = 0; j < max; j++) { - for(k = 0; k < 8; k++) { - memset(&sd, 0, sizeof(sd)); - sd.SRB_Cmd = SC_GET_DEV_TYPE; - sd.SRB_HaId = i; - sd.SRB_Target = j; - sd.SRB_Lun = k; - SendASPI32Command((LPSRB)&sd); - if(sd.SRB_Status == SS_COMP) { - if(sd.SRB_DeviceType == DTYPE_CDROM) { - cdr++; - if(cdr > cdromCount) { - hid = i; - tid = j; - lun = k; - cdromCount++; - bHaveDev = TRUE; - } - } - } - if(bHaveDev) break; - } - if(bHaveDev) break; - } - - } - } else { - BX_PANIC(("Could not load ASPI drivers, so cdrom access will fail")); - } - fd=1; - } else { - BX_INFO(("Using direct access for CDROM")); - hFile=CreateFile((char *)&drive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); - if (hFile !=(void *)0xFFFFFFFF) - fd=1; - } -#elif defined(__APPLE__) - if(strcmp(path, "drive") == 0) - { - mach_port_t masterPort = NULL; - io_iterator_t mediaIterator; - kern_return_t kernResult; - - BX_INFO(( "Insert CDROM" )); - - kernResult = FindEjectableCDMedia( &mediaIterator, &masterPort ); - if ( kernResult != KERN_SUCCESS ) { - BX_INFO (("Unable to find CDROM")); - return false; - } - - kernResult = GetDeviceFilePath( mediaIterator, CDDevicePath, sizeof( CDDevicePath ) ); - if ( kernResult != KERN_SUCCESS ) { - BX_INFO (("Unable to get CDROM device file path" )); - return false; - } - - // Here a cdrom was found so see if we can read from it. - // At this point a failure will result in panic. - if ( strlen( CDDevicePath ) ) { - fd = open(CDDevicePath, O_RDONLY); - } - } - else - { - fd = open(path, O_RDONLY); - } -#else - // all platforms except win32 - fd = open(path, O_RDONLY); -#endif - if (fd < 0) { - BX_ERROR(( "open cd failed for %s: %s", path, strerror(errno))); - return(false); - } - - // I just see if I can read a sector to verify that a - // CD is in the drive and readable. -#ifdef WIN32 - if(bUseASPI) { - return ReadCDSector(hid, tid, lun, 0, buffer, BX_CD_FRAMESIZE); - } else { - if (!ReadFile(hFile, (void *) buffer, BX_CD_FRAMESIZE, (unsigned long *) &ret, NULL)) { - CloseHandle(hFile); - fd = -1; - BX_DEBUG(( "insert_cdrom: read returns error." )); - return(false); - } - } -#else - // do fstat to determine if it's a file or a device, then set using_file. - struct stat stat_buf; - ret = fstat (fd, &stat_buf); - if (ret) { - BX_PANIC (("fstat cdrom file returned error: %s", strerror (errno))); - } - if (S_ISREG (stat_buf.st_mode)) { - using_file = 1; - BX_INFO (("Opening image file %s as a cd.", path)); - } else { - using_file = 0; - BX_INFO (("Using direct access for cdrom.")); - } - - ret = read(fd, (char*) &buffer, BX_CD_FRAMESIZE); - if (ret < 0) { - close(fd); - fd = -1; - BX_DEBUG(( "insert_cdrom: read returns error: %s", strerror (errno) )); - return(false); - } -#endif - return(true); -} - - int -cdrom_interface::start_cdrom() -{ - // Spin up the cdrom drive. - - if (fd >= 0) { -#if defined(__NetBSD__) - if (ioctl (fd, CDIOCSTART) < 0) - BX_DEBUG(( "start_cdrom: start returns error: %s", strerror (errno) )); - return(true); -#else - BX_INFO(("start_cdrom: your OS is not supported yet.")); - return(false); // OS not supported yet, return false always. -#endif - } - return(false); -} - - void -cdrom_interface::eject_cdrom() -{ - // Logically eject the CD. I suppose we could stick in - // some ioctl() calls to really eject the CD as well. - - if (fd >= 0) { -#if (defined(__OpenBSD__) || defined(__FreeBSD__)) - (void) ioctl (fd, CDIOCALLOW); - if (ioctl (fd, CDIOCEJECT) < 0) - BX_DEBUG(( "eject_cdrom: eject returns error." )); -#endif - -#ifdef WIN32 -if (using_file == 0) -{ - if(bUseASPI) { - } else { - DWORD lpBytesReturned; - DeviceIoControl(hFile, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &lpBytesReturned, NULL); - } -} -#else // WIN32 - -#if __linux__ - if (!using_file) - ioctl (fd, CDROMEJECT, NULL); -#endif - - close(fd); -#endif // WIN32 - fd = -1; - } -} - - - bx_bool -cdrom_interface::read_toc(uint8* buf, int* length, bx_bool msf, int start_track) -{ - // Read CD TOC. Returns false if start track is out of bounds. - - if (fd < 0) { - BX_PANIC(("cdrom: read_toc: file not open.")); - } - -#if defined(WIN32) - if (1) { // This is a hack and works okay if there's one rom track only -#else - if (using_file) { -#endif - // From atapi specs : start track can be 0-63, AA - if ((start_track > 1) && (start_track != 0xaa)) - return false; - - buf[2] = 1; - buf[3] = 1; - - int len = 4; - if (start_track <= 1) { - buf[len++] = 0; // Reserved - buf[len++] = 0x14; // ADR, control - buf[len++] = 1; // Track number - buf[len++] = 0; // Reserved - - // Start address - if (msf) { - buf[len++] = 0; // reserved - buf[len++] = 0; // minute - buf[len++] = 2; // second - buf[len++] = 0; // frame - } else { - buf[len++] = 0; - buf[len++] = 0; - buf[len++] = 0; - buf[len++] = 0; // logical sector 0 - } - } - - // Lead out track - buf[len++] = 0; // Reserved - buf[len++] = 0x16; // ADR, control - buf[len++] = 0xaa; // Track number - buf[len++] = 0; // Reserved - - uint32 blocks = capacity(); - - // Start address - if (msf) { - buf[len++] = 0; // reserved - buf[len++] = (uint8)(((blocks + 150) / 75) / 60); // minute - buf[len++] = (uint8)(((blocks + 150) / 75) % 60); // second - buf[len++] = (uint8)((blocks + 150) % 75); // frame; - } else { - buf[len++] = (blocks >> 24) & 0xff; - buf[len++] = (blocks >> 16) & 0xff; - buf[len++] = (blocks >> 8) & 0xff; - buf[len++] = (blocks >> 0) & 0xff; - } - - buf[0] = ((len-2) >> 8) & 0xff; - buf[1] = (len-2) & 0xff; - - *length = len; - - return true; - } - // all these implementations below are the platform-dependent code required - // to read the TOC from a physical cdrom. -#ifdef WIN32 - { -/* #define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM - #define IOCTL_CDROM_READ_TOC CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS) - unsigned long iBytesReturned; - DeviceIoControl(hFile, IOCTL_CDROM_READ_TOC, NULL, 0, NULL, 0, &iBytesReturned, NULL); */ - BX_ERROR (("WARNING: read_toc is not implemented, just returning length=1")); - *length = 1; - return true; - } -#elif __linux__ || defined(__sun) - { - struct cdrom_tochdr tochdr; - if (ioctl(fd, CDROMREADTOCHDR, &tochdr)) - BX_PANIC(("cdrom: read_toc: READTOCHDR failed.")); - - if ((start_track > tochdr.cdth_trk1) && (start_track != 0xaa)) - return false; - - buf[2] = tochdr.cdth_trk0; - buf[3] = tochdr.cdth_trk1; - - if (start_track < tochdr.cdth_trk0) - start_track = tochdr.cdth_trk0; - - int len = 4; - for (int i = start_track; i <= tochdr.cdth_trk1; i++) { - struct cdrom_tocentry tocentry; - tocentry.cdte_format = (msf) ? CDROM_MSF : CDROM_LBA; - tocentry.cdte_track = i; - if (ioctl(fd, CDROMREADTOCENTRY, &tocentry)) - BX_PANIC(("cdrom: read_toc: READTOCENTRY failed.")); - buf[len++] = 0; // Reserved - buf[len++] = (tocentry.cdte_adr << 4) | tocentry.cdte_ctrl ; // ADR, control - buf[len++] = i; // Track number - buf[len++] = 0; // Reserved - - // Start address - if (msf) { - buf[len++] = 0; // reserved - buf[len++] = tocentry.cdte_addr.msf.minute; - buf[len++] = tocentry.cdte_addr.msf.second; - buf[len++] = tocentry.cdte_addr.msf.frame; - } else { - buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 24) & 0xff; - buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 16) & 0xff; - buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 8) & 0xff; - buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 0) & 0xff; - } - } - - // Lead out track - struct cdrom_tocentry tocentry; - tocentry.cdte_format = (msf) ? CDROM_MSF : CDROM_LBA; -#ifdef CDROM_LEADOUT - tocentry.cdte_track = CDROM_LEADOUT; -#else - tocentry.cdte_track = 0xaa; -#endif - if (ioctl(fd, CDROMREADTOCENTRY, &tocentry)) - BX_PANIC(("cdrom: read_toc: READTOCENTRY lead-out failed.")); - buf[len++] = 0; // Reserved - buf[len++] = (tocentry.cdte_adr << 4) | tocentry.cdte_ctrl ; // ADR, control - buf[len++] = 0xaa; // Track number - buf[len++] = 0; // Reserved - - // Start address - if (msf) { - buf[len++] = 0; // reserved - buf[len++] = tocentry.cdte_addr.msf.minute; - buf[len++] = tocentry.cdte_addr.msf.second; - buf[len++] = tocentry.cdte_addr.msf.frame; - } else { - buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 24) & 0xff; - buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 16) & 0xff; - buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 8) & 0xff; - buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 0) & 0xff; - } - - buf[0] = ((len-2) >> 8) & 0xff; - buf[1] = (len-2) & 0xff; - - *length = len; - - return true; - } -#elif (defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)) - { - struct ioc_toc_header h; - struct ioc_read_toc_entry t; - - if (ioctl (fd, CDIOREADTOCHEADER, &h) < 0) - BX_PANIC(("cdrom: read_toc: READTOCHDR failed.")); - - if ((start_track > h.ending_track) && (start_track != 0xaa)) - return false; - - buf[2] = h.starting_track; - buf[3] = h.ending_track; - - if (start_track < h.starting_track) - start_track = h.starting_track; - - int len = 4; - for (int i = start_track; i <= h.ending_track; i++) { - struct cd_toc_entry tocentry; - t.address_format = (msf) ? CD_MSF_FORMAT : CD_LBA_FORMAT; - t.starting_track = i; - t.data_len = sizeof(tocentry); - t.data = &tocentry; - - if (ioctl (fd, CDIOREADTOCENTRYS, &t) < 0) - BX_PANIC(("cdrom: read_toc: READTOCENTRY failed.")); - - buf[len++] = 0; // Reserved - buf[len++] = (tocentry.addr_type << 4) | tocentry.control ; // ADR, control - buf[len++] = i; // Track number - buf[len++] = 0; // Reserved - - // Start address - if (msf) { - buf[len++] = 0; // reserved - buf[len++] = tocentry.addr.msf.minute; - buf[len++] = tocentry.addr.msf.second; - buf[len++] = tocentry.addr.msf.frame; - } else { - buf[len++] = (((unsigned)tocentry.addr.lba) >> 24) & 0xff; - buf[len++] = (((unsigned)tocentry.addr.lba) >> 16) & 0xff; - buf[len++] = (((unsigned)tocentry.addr.lba) >> 8) & 0xff; - buf[len++] = (((unsigned)tocentry.addr.lba) >> 0) & 0xff; - } - } - - // Lead out track - struct cd_toc_entry tocentry; - t.address_format = (msf) ? CD_MSF_FORMAT : CD_LBA_FORMAT; - t.starting_track = 0xaa; - t.data_len = sizeof(tocentry); - t.data = &tocentry; - - if (ioctl (fd, CDIOREADTOCENTRYS, &t) < 0) - BX_PANIC(("cdrom: read_toc: READTOCENTRY lead-out failed.")); - - buf[len++] = 0; // Reserved - buf[len++] = (tocentry.addr_type << 4) | tocentry.control ; // ADR, control - buf[len++] = 0xaa; // Track number - buf[len++] = 0; // Reserved - - // Start address - if (msf) { - buf[len++] = 0; // reserved - buf[len++] = tocentry.addr.msf.minute; - buf[len++] = tocentry.addr.msf.second; - buf[len++] = tocentry.addr.msf.frame; - } else { - buf[len++] = (((unsigned)tocentry.addr.lba) >> 24) & 0xff; - buf[len++] = (((unsigned)tocentry.addr.lba) >> 16) & 0xff; - buf[len++] = (((unsigned)tocentry.addr.lba) >> 8) & 0xff; - buf[len++] = (((unsigned)tocentry.addr.lba) >> 0) & 0xff; - } - - buf[0] = ((len-2) >> 8) & 0xff; - buf[1] = (len-2) & 0xff; - - *length = len; - - return true; - } -#elif defined(__APPLE__) - // Read CD TOC. Returns false if start track is out of bounds. - -#if 1 - { - struct _CDTOC * toc = ReadTOC( CDDevicePath ); - - if ((start_track > toc->last_session) && (start_track != 0xaa)) - return false; - - buf[2] = toc->first_session; - buf[3] = toc->last_session; - - if (start_track < toc->first_session) - start_track = toc->first_session; - - int len = 4; - for (int i = start_track; i <= toc->last_session; i++) { - buf[len++] = 0; // Reserved - buf[len++] = toc->trackdesc[i].ctrl_adr ; // ADR, control - buf[len++] = i; // Track number - buf[len++] = 0; // Reserved - - // Start address - if (msf) { - buf[len++] = 0; // reserved - buf[len++] = toc->trackdesc[i].address.minute; - buf[len++] = toc->trackdesc[i].address.second; - buf[len++] = toc->trackdesc[i].address.frame; - } else { - unsigned lba = (unsigned)(MSF_TO_LBA(toc->trackdesc[i].address)); - buf[len++] = (lba >> 24) & 0xff; - buf[len++] = (lba >> 16) & 0xff; - buf[len++] = (lba >> 8) & 0xff; - buf[len++] = (lba >> 0) & 0xff; - } - } - - // Lead out track - buf[len++] = 0; // Reserved - buf[len++] = 0x16; // ADR, control - buf[len++] = 0xaa; // Track number - buf[len++] = 0; // Reserved - - uint32 blocks = capacity(); - - // Start address - if (msf) { - buf[len++] = 0; // reserved - buf[len++] = (uint8)(((blocks + 150) / 75) / 60); // minute - buf[len++] = (uint8)(((blocks + 150) / 75) % 60); // second - buf[len++] = (uint8)((blocks + 150) % 75); // frame; - } else { - buf[len++] = (blocks >> 24) & 0xff; - buf[len++] = (blocks >> 16) & 0xff; - buf[len++] = (blocks >> 8) & 0xff; - buf[len++] = (blocks >> 0) & 0xff; - } - - buf[0] = ((len-2) >> 8) & 0xff; - buf[1] = (len-2) & 0xff; - - *length = len; - - return true; -// BX_INFO(( "Read TOC - Not Implemented" )); -// return false; - } -#else - BX_INFO(( "Read TOC - Not Implemented" )); - return false; -#endif -#else - BX_INFO(("read_toc: your OS is not supported yet.")); - return(false); // OS not supported yet, return false always. -#endif -} - - - uint32 -cdrom_interface::capacity() -{ - // Return CD-ROM capacity. I believe you want to return - // the number of blocks of capacity the actual media has. - -#if !defined WIN32 - // win32 has its own way of doing this - if (using_file) { - // return length of the image file - struct stat stat_buf; - int ret = fstat (fd, &stat_buf); - if (ret) { - BX_PANIC (("fstat on cdrom image returned err: %s", strerror(errno))); - } - BX_INFO (("cdrom size is %lld bytes", stat_buf.st_size)); - if ((stat_buf.st_size % 2048) != 0) { - BX_ERROR (("expected cdrom image to be a multiple of 2048 bytes")); - } - return stat_buf.st_size / 2048; - } -#endif - -#ifdef __BEOS__ - return GetNumDeviceBlocks(fd, BX_CD_FRAMESIZE); -#elif defined(__sun) - { - struct stat buf = {0}; - - if (fd < 0) { - BX_PANIC(("cdrom: capacity: file not open.")); - } - - if( fstat(fd, &buf) != 0 ) - BX_PANIC(("cdrom: capacity: stat() failed.")); - - return(buf.st_size); - } -#elif (defined(__NetBSD__) || defined(__OpenBSD__)) - { - // We just read the disklabel, imagine that... - struct disklabel lp; - - if (fd < 0) - BX_PANIC(("cdrom: capacity: file not open.")); - - if (ioctl(fd, DIOCGDINFO, &lp) < 0) - BX_PANIC(("cdrom: ioctl(DIOCGDINFO) failed")); - - BX_DEBUG(( "capacity: %u", lp.d_secperunit )); - return(lp.d_secperunit); - } -#elif defined(__linux__) - { - // Read the TOC to get the data size, since BLKGETSIZE doesn't work on - // non-ATAPI drives. This is based on Keith Jones code below. - // 21 June 2001 - - int i, dtrk_lba, num_sectors; - int dtrk = 0; - struct cdrom_tochdr td; - struct cdrom_tocentry te; - - if (fd < 0) - BX_PANIC(("cdrom: capacity: file not open.")); - - if (ioctl(fd, CDROMREADTOCHDR, &td) < 0) - BX_PANIC(("cdrom: ioctl(CDROMREADTOCHDR) failed")); - - num_sectors = -1; - dtrk_lba = -1; - - for (i = td.cdth_trk0; i <= td.cdth_trk1; i++) { - te.cdte_track = i; - te.cdte_format = CDROM_LBA; - if (ioctl(fd, CDROMREADTOCENTRY, &te) < 0) - BX_PANIC(("cdrom: ioctl(CDROMREADTOCENTRY) failed")); - - if (dtrk_lba != -1) { - num_sectors = te.cdte_addr.lba - dtrk_lba; - break; - } - if (te.cdte_ctrl & CDROM_DATA_TRACK) { - dtrk = i; - dtrk_lba = te.cdte_addr.lba; - } - } - - if (num_sectors < 0) { - if (dtrk_lba != -1) { - te.cdte_track = CDROM_LEADOUT; - te.cdte_format = CDROM_LBA; - if (ioctl(fd, CDROMREADTOCENTRY, &te) < 0) - BX_PANIC(("cdrom: ioctl(CDROMREADTOCENTRY) failed")); - num_sectors = te.cdte_addr.lba - dtrk_lba; - } else - BX_PANIC(("cdrom: no data track found")); - } - - BX_INFO(("cdrom: Data track %d, length %d", dtrk, num_sectors)); - - return(num_sectors); - - } -#elif defined(__FreeBSD__) - { - // Read the TOC to get the size of the data track. - // Keith Jones , 16 January 2000 - -#define MAX_TRACKS 100 - - int i, num_tracks, num_sectors; - struct ioc_toc_header td; - struct ioc_read_toc_entry rte; - struct cd_toc_entry toc_buffer[MAX_TRACKS + 1]; - - if (fd < 0) - BX_PANIC(("cdrom: capacity: file not open.")); - - if (ioctl(fd, CDIOREADTOCHEADER, &td) < 0) - BX_PANIC(("cdrom: ioctl(CDIOREADTOCHEADER) failed")); - - num_tracks = (td.ending_track - td.starting_track) + 1; - if (num_tracks > MAX_TRACKS) - BX_PANIC(("cdrom: TOC is too large")); - - rte.address_format = CD_LBA_FORMAT; - rte.starting_track = td.starting_track; - rte.data_len = (num_tracks + 1) * sizeof(struct cd_toc_entry); - rte.data = toc_buffer; - if (ioctl(fd, CDIOREADTOCENTRYS, &rte) < 0) - BX_PANIC(("cdrom: ioctl(CDIOREADTOCENTRYS) failed")); - - num_sectors = -1; - for (i = 0; i < num_tracks; i++) { - if (rte.data[i].control & 4) { /* data track */ - num_sectors = ntohl(rte.data[i + 1].addr.lba) - - ntohl(rte.data[i].addr.lba); - BX_INFO(( "cdrom: Data track %d, length %d", - rte.data[i].track, num_sectors)); - break; - } - } - - if (num_sectors < 0) - BX_PANIC(("cdrom: no data track found")); - - return(num_sectors); - - } -#elif defined WIN32 - { - if(bUseASPI) { - return (GetCDCapacity(hid, tid, lun) / 2352); - } else if(using_file) { - ULARGE_INTEGER FileSize; - FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart); - return (FileSize.QuadPart / 2048); - } else { /* direct device access */ - DWORD SectorsPerCluster; - DWORD TotalNumOfClusters; - GetDiskFreeSpace( path, &SectorsPerCluster, NULL, NULL, &TotalNumOfClusters); - return (TotalNumOfClusters * SectorsPerCluster); - } - } -#elif defined __APPLE__ -// Find the size of the first data track on the cd. This has produced -// the same results as the linux version on every cd I have tried, about -// 5. The differences here seem to be that the entries in the TOC when -// retrieved from the IOKit interface appear in a reversed order when -// compared with the linux READTOCENTRY ioctl. - { - // Return CD-ROM capacity. I believe you want to return - // the number of bytes of capacity the actual media has. - - BX_INFO(( "Capacity" )); - - struct _CDTOC * toc = ReadTOC( CDDevicePath ); - - if ( toc == NULL ) { - BX_PANIC(( "capacity: Failed to read toc" )); - } - - size_t toc_entries = ( toc->length - 2 ) / sizeof( struct _CDTOC_Desc ); - - BX_DEBUG(( "reading %d toc entries\n", toc_entries )); - - int start_sector = -1; - int data_track = -1; - - // Iterate through the list backward. Pick the first data track and - // get the address of the immediately previous (or following depending - // on how you look at it). The difference in the sector numbers - // is returned as the sized of the data track. - for ( int i=toc_entries - 1; i>=0; i-- ) { - - BX_DEBUG(( "session %d ctl_adr %d tno %d point %d lba %d z %d p lba %d\n", - (int)toc->trackdesc[i].session, - (int)toc->trackdesc[i].ctrl_adr, - (int)toc->trackdesc[i].tno, - (int)toc->trackdesc[i].point, - MSF_TO_LBA( toc->trackdesc[i].address ), - (int)toc->trackdesc[i].zero, - MSF_TO_LBA(toc->trackdesc[i].p ))); - - if ( start_sector != -1 ) { - - start_sector = MSF_TO_LBA(toc->trackdesc[i].p) - start_sector; - break; - - } - - if (( toc->trackdesc[i].ctrl_adr >> 4) != 1 ) continue; - - if ( toc->trackdesc[i].ctrl_adr & 0x04 ) { - - data_track = toc->trackdesc[i].point; - - start_sector = MSF_TO_LBA(toc->trackdesc[i].p); - - } - - } - - free( toc ); - - if ( start_sector == -1 ) { - start_sector = 0; - } - - BX_INFO(("first data track %d data size is %d", data_track, start_sector)); - - return start_sector; - } -#else - BX_ERROR(( "capacity: your OS is not supported yet." )); - return(0); -#endif -} - - void BX_CPP_AttrRegparmN(2) -cdrom_interface::read_block(uint8* buf, int lba) -{ - // Read a single block from the CD - -#ifdef WIN32 - LARGE_INTEGER pos; -#else - off_t pos; -#endif - ssize_t n; - -#ifdef WIN32 - if(bUseASPI) { - ReadCDSector(hid, tid, lun, lba, buf, BX_CD_FRAMESIZE); - n = BX_CD_FRAMESIZE; - } else { - pos.QuadPart = (LONGLONG)lba*BX_CD_FRAMESIZE; - pos.LowPart = SetFilePointer(hFile, pos.LowPart, &pos.HighPart, SEEK_SET); - if ((pos.LowPart == 0xffffffff) && (GetLastError() != NO_ERROR)) { - BX_PANIC(("cdrom: read_block: SetFilePointer returned error.")); - } - ReadFile(hFile, (void *) buf, BX_CD_FRAMESIZE, (unsigned long *) &n, NULL); - } -#elif defined(__APPLE__) -#define CD_SEEK_DISTANCE kCDSectorSizeWhole - if(using_file) - { - pos = lseek(fd, lba*BX_CD_FRAMESIZE, SEEK_SET); - if (pos < 0) { - BX_PANIC(("cdrom: read_block: lseek returned error.")); - } - n = read(fd, buf, BX_CD_FRAMESIZE); - } - else - { - // This seek will leave us 16 bytes from the start of the data - // hence the magic number. - pos = lseek(fd, lba*CD_SEEK_DISTANCE + 16, SEEK_SET); - if (pos < 0) { - BX_PANIC(("cdrom: read_block: lseek returned error.")); - } - n = read(fd, buf, CD_FRAMESIZE); - } -#else - pos = lseek(fd, lba*BX_CD_FRAMESIZE, SEEK_SET); - if (pos < 0) { - BX_PANIC(("cdrom: read_block: lseek returned error.")); - } - n = read(fd, (char*) buf, BX_CD_FRAMESIZE); -#endif - - if (n != BX_CD_FRAMESIZE) { - BX_PANIC(("cdrom: read_block: read returned %d", - (int) n)); - } -} - -#endif /* if BX_SUPPORT_CDROM */ diff --git a/tools/ioemu/iodev/cdrom.h b/tools/ioemu/iodev/cdrom.h deleted file mode 100644 index 29fdfaff85..0000000000 --- a/tools/ioemu/iodev/cdrom.h +++ /dev/null @@ -1,67 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: cdrom.h,v 1.13 2003/08/19 00:37:03 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -// Header file for low-level OS specific CDROM emulation - - -class cdrom_interface : public logfunctions { -public: - cdrom_interface(char *dev); - ~cdrom_interface(void); - void init(void); - - // Load CD-ROM. Returns false if CD is not ready. - bx_bool insert_cdrom(char *dev = NULL); - - // Logically eject the CD. - void eject_cdrom(); - - // Read CD TOC. Returns false if start track is out of bounds. - bx_bool read_toc(uint8* buf, int* length, bx_bool msf, int start_track); - - // Return CD-ROM capacity (in 2048 byte frames) - uint32 capacity(); - - // Read a single block from the CD - void read_block(uint8* buf, int lba) BX_CPP_AttrRegparmN(2); - - // Start (spin up) the CD. - int start_cdrom(); - -private: - int fd; - char *path; - - int using_file; -#ifdef WIN32 - HANDLE hFile; - int hid; - int tid; - int lun; -#endif - }; - diff --git a/tools/ioemu/iodev/cdrom_beos.h b/tools/ioemu/iodev/cdrom_beos.h deleted file mode 100644 index 8a22d5c0f8..0000000000 --- a/tools/ioemu/iodev/cdrom_beos.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef CDROM_BEOS_H -#define CDROM_BEOS_H - -#include //for off_t - -off_t GetNumDeviceBlocks(int fd, int block_size); -int GetLogicalBlockSize(int fd); -int GetDeviceBlockSize(int fd); - -#endif diff --git a/tools/ioemu/iodev/cmos.cc b/tools/ioemu/iodev/cmos.cc deleted file mode 100644 index fbf3144989..0000000000 --- a/tools/ioemu/iodev/cmos.cc +++ /dev/null @@ -1,824 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: cmos.cc,v 1.44 2003/12/27 13:43:41 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - - - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" - -#define LOG_THIS theCmosDevice-> - -bx_cmos_c *theCmosDevice = NULL; - -// CMOS register definitions from Ralf Brown's interrupt list v6.1, in a file -// called cmos.lst. In cases where there are multiple uses for a given -// register in the interrupt list, I only listed the purpose that Bochs -// actually uses it for, but I wrote "alternatives" next to it. -#define REG_SEC 0x00 -#define REG_SEC_ALARM 0x01 -#define REG_MIN 0x02 -#define REG_MIN_ALARM 0x03 -#define REG_HOUR 0x04 -#define REG_HOUR_ALARM 0x05 -#define REG_WEEK_DAY 0x06 -#define REG_MONTH_DAY 0x07 -#define REG_MONTH 0x08 -#define REG_YEAR 0x09 -#define REG_STAT_A 0x0a -#define REG_STAT_B 0x0b -#define REG_STAT_C 0x0c -#define REG_STAT_D 0x0d -#define REG_DIAGNOSTIC_STATUS 0x0e /* alternatives */ -#define REG_SHUTDOWN_STATUS 0x0f -#define REG_EQUIPMENT_BYTE 0x14 -#define REG_CSUM_HIGH 0x2e -#define REG_CSUM_LOW 0x2f -#define REG_IBM_CENTURY_BYTE 0x32 /* alternatives */ -#define REG_IBM_PS2_CENTURY_BYTE 0x37 /* alternatives */ - -// Bochs CMOS map (to be completed) -// -// Idx Len Description -// 0x15 2 Base memory in 1k -// 0x17 2 Memory size above 1M in 1k -// 0x30 2 Memory size above 1M in 1k -// 0x34 2 Memory size above 16M in 64k -// - -// check that BX_NUM_CMOS_REGS is 64 or 128 -#if (BX_NUM_CMOS_REGS == 64) -#elif (BX_NUM_CMOS_REGS == 128) -#else -#error "Invalid BX_NUM_CMOS_REGS value in config.h" -#endif - - - int -libcmos_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - theCmosDevice = new bx_cmos_c (); - bx_devices.pluginCmosDevice = theCmosDevice; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theCmosDevice, BX_PLUGIN_CMOS); - return(0); // Success -} - - void -libcmos_LTX_plugin_fini(void) -{ -} - -bx_cmos_c::bx_cmos_c(void) -{ - put("CMOS"); - settype(CMOSLOG); - - unsigned i; - for (i=0; iget () == BX_CLOCK_TIME0_LOCAL) { - BX_INFO(("Using local time for initial clock")); - BX_CMOS_THIS s.timeval = time(NULL); - } - // utc - else if (bx_options.clock.Otime0->get () == BX_CLOCK_TIME0_UTC) { - bx_bool utc_ok = 0; - - BX_INFO(("Using utc time for initial clock")); - - BX_CMOS_THIS s.timeval = time(NULL); - -#if BX_HAVE_GMTIME -#if BX_HAVE_MKTIME - struct tm *utc_holder = gmtime(&BX_CMOS_THIS s.timeval); - utc_holder->tm_isdst = -1; - utc_ok = 1; - BX_CMOS_THIS s.timeval = mktime(utc_holder); -#elif BX_HAVE_TIMELOCAL - struct tm *utc_holder = gmtime(&BX_CMOS_THIS s.timeval); - utc_holder->tm_isdst = 0; // XXX Is this correct??? - utc_ok = 1; - BX_CMOS_THIS s.timeval = timelocal(utc_holder); -#endif //BX_HAVE_MKTIME -#endif //BX_HAVE_GMTIME - - if (!utc_ok) { - BX_ERROR(("UTC time is not supported on your platform. Using current time(NULL)")); - } - } - else { - BX_INFO(("Using specified time for initial clock")); - BX_CMOS_THIS s.timeval = bx_options.clock.Otime0->get (); - } -#endif // BX_USE_SPECIFIED_TIME0 != 0 - - char *tmptime; - while( (tmptime = strdup(ctime(&(BX_CMOS_THIS s.timeval)))) == NULL) { - BX_PANIC(("Out of memory.")); - } - tmptime[strlen(tmptime)-1]='\0'; - - BX_INFO(("Setting initial clock to: %s (time0=%u)", tmptime, (Bit32u)BX_CMOS_THIS s.timeval)); - - update_clock(); - BX_CMOS_THIS s.timeval_change = 0; - - // load CMOS from image file if requested. - if (bx_options.cmos.OcmosImage->get ()) { - // CMOS image file requested - int fd, ret; - struct stat stat_buf; - - fd = open(bx_options.cmos.Opath->getptr (), O_RDONLY -#ifdef O_BINARY - | O_BINARY -#endif - ); - if (fd < 0) { - BX_PANIC(("trying to open cmos image file '%s'", - bx_options.cmos.Opath->getptr ())); - } - ret = fstat(fd, &stat_buf); - if (ret) { - BX_PANIC(("CMOS: could not fstat() image file.")); - } - if (stat_buf.st_size != BX_NUM_CMOS_REGS) { - BX_PANIC(("CMOS: image file not same size as BX_NUM_CMOS_REGS.")); - } - - ret = ::read(fd, (bx_ptr_t) BX_CMOS_THIS s.reg, BX_NUM_CMOS_REGS); - if (ret != BX_NUM_CMOS_REGS) { - BX_PANIC(("CMOS: error reading cmos file.")); - } - close(fd); - BX_INFO(("successfuly read from image file '%s'.", - bx_options.cmos.Opath->getptr ())); - } - else { - // CMOS values generated - BX_CMOS_THIS s.reg[REG_STAT_A] = 0x26; - BX_CMOS_THIS s.reg[REG_STAT_B] = 0x02; - BX_CMOS_THIS s.reg[REG_STAT_C] = 0x00; - BX_CMOS_THIS s.reg[REG_STAT_D] = 0x80; -#if BX_SUPPORT_FPU == 1 - BX_CMOS_THIS s.reg[REG_EQUIPMENT_BYTE] |= 0x02; -#endif - } -} - - void -bx_cmos_c::reset(unsigned type) -{ - BX_CMOS_THIS s.cmos_mem_address = 0; - - // RESET affects the following registers: - // CRA: no effects - // CRB: bits 4,5,6 forced to 0 - // CRC: bits 4,5,6,7 forced to 0 - // CRD: no effects - BX_CMOS_THIS s.reg[REG_STAT_B] &= 0x8f; - BX_CMOS_THIS s.reg[REG_STAT_C] = 0; - - // One second timer for updating clock & alarm functions - bx_pc_system.activate_timer(BX_CMOS_THIS s.one_second_timer_index, - 1000000, 1); - - // handle periodic interrupt rate select - BX_CMOS_THIS CRA_change(); -} - - void -bx_cmos_c::CRA_change(void) -{ - unsigned nibble; - - // Periodic Interrupt timer - nibble = BX_CMOS_THIS s.reg[REG_STAT_A] & 0x0f; - if (nibble == 0) { - // No Periodic Interrupt Rate when 0, deactivate timer - bx_pc_system.deactivate_timer(BX_CMOS_THIS s.periodic_timer_index); - BX_CMOS_THIS s.periodic_interval_usec = (Bit32u) -1; // max value - } - else { - // values 0001b and 0010b are the same as 1000b and 1001b - if (nibble <= 2) - nibble += 7; - BX_CMOS_THIS s.periodic_interval_usec = (unsigned) (1000000.0L / - (32768.0L / (1 << (nibble - 1)))); - - // if Periodic Interrupt Enable bit set, activate timer - if ( BX_CMOS_THIS s.reg[REG_STAT_B] & 0x40 ) - bx_pc_system.activate_timer(BX_CMOS_THIS s.periodic_timer_index, - BX_CMOS_THIS s.periodic_interval_usec, 1); - else - bx_pc_system.deactivate_timer(BX_CMOS_THIS s.periodic_timer_index); - } -} - - - // static IO port read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_cmos_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_CMOS_SMF - bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr; - - return( class_ptr->read(address, io_len) ); -} - - Bit32u -bx_cmos_c::read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif - Bit8u ret8; - - if (bx_dbg.cmos) - BX_INFO(("CMOS read of CMOS register 0x%02x", - (unsigned) BX_CMOS_THIS s.cmos_mem_address)); - - - switch (address) { - case 0x0070: - BX_INFO(("read of index port 0x70. returning 0xff")); - // Volker says his boxes return 0xff - //ret8 = BX_CMOS_THIS s.cmos_mem_address; - return(0xff); - break; - case 0x0071: - if (BX_CMOS_THIS s.cmos_mem_address >= BX_NUM_CMOS_REGS) { - BX_PANIC(("unsupported cmos io read, register(0x%02x)!", - (unsigned) BX_CMOS_THIS s.cmos_mem_address)); - } - - ret8 = BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address]; - // all bits of Register C are cleared after a read occurs. - if (BX_CMOS_THIS s.cmos_mem_address == REG_STAT_C) { - BX_CMOS_THIS s.reg[REG_STAT_C] = 0x00; - DEV_pic_lower_irq(8); - } - return(ret8); - break; - - default: - BX_PANIC(("unsupported cmos read, address=0x%04x!", - (unsigned) address)); - return(0); - break; - } -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_cmos_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_CMOS_SMF - bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - - void -bx_cmos_c::write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_CMOS_SMF - - if (bx_dbg.cmos) - BX_INFO(("CMOS write to address: 0x%04x = 0x%02x", - (unsigned) address, (unsigned) value)); - - - switch (address) { - case 0x0070: -#if (BX_NUM_CMOS_REGS == 64) - BX_CMOS_THIS s.cmos_mem_address = value & 0x3F; -#else - BX_CMOS_THIS s.cmos_mem_address = value & 0x7F; -#endif - break; - - case 0x0071: - if (BX_CMOS_THIS s.cmos_mem_address >= BX_NUM_CMOS_REGS) { - BX_PANIC(("unsupported cmos io write, register(0x%02x) = 0x%02x !", - (unsigned) BX_CMOS_THIS s.cmos_mem_address, (unsigned) value)); - return; - } - switch (BX_CMOS_THIS s.cmos_mem_address) { - case REG_SEC_ALARM: // seconds alarm - case REG_MIN_ALARM: // minutes alarm - case REG_HOUR_ALARM: // hours alarm - BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address] = value; - BX_DEBUG(("alarm time changed to %02x:%02x:%02x", BX_CMOS_THIS s.reg[REG_HOUR_ALARM], - BX_CMOS_THIS s.reg[REG_MIN_ALARM], BX_CMOS_THIS s.reg[REG_SEC_ALARM])); - return; - break; - - case REG_SEC: // seconds - case REG_MIN: // minutes - case REG_HOUR: // hours - case REG_WEEK_DAY: // day of the week - case REG_MONTH_DAY: // day of the month - case REG_MONTH: // month - case REG_YEAR: // year - case REG_IBM_CENTURY_BYTE: // century - case REG_IBM_PS2_CENTURY_BYTE: // century (PS/2) - //BX_INFO(("write reg 0x%02x: value = 0x%02x", - // (unsigned) BX_CMOS_THIS s.cmos_mem_address, (unsigned) value); - BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address] = value; - if (BX_CMOS_THIS s.cmos_mem_address == REG_IBM_PS2_CENTURY_BYTE) { - BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE] = value; - } - if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x80) { - BX_CMOS_THIS s.timeval_change = 1; - } else { - update_timeval(); - } - return; - break; - - case REG_STAT_A: // Control Register A - // bit 7: Update in Progress (read-only) - // 1 = signifies time registers will be updated within 244us - // 0 = time registers will not occur before 244us - // note: this bit reads 0 when CRB bit 7 is 1 - // bit 6..4: Divider Chain Control - // 000 oscillator disabled - // 001 oscillator disabled - // 010 Normal operation - // 011 TEST - // 100 TEST - // 101 TEST - // 110 Divider Chain RESET - // 111 Divider Chain RESET - // bit 3..0: Periodic Interrupt Rate Select - // 0000 None - // 0001 3.90625 ms - // 0010 7.8125 ms - // 0011 122.070 us - // 0100 244.141 us - // 0101 488.281 us - // 0110 976.562 us - // 0111 1.953125 ms - // 1000 3.90625 ms - // 1001 7.8125 ms - // 1010 15.625 ms - // 1011 31.25 ms - // 1100 62.5 ms - // 1101 125 ms - // 1110 250 ms - // 1111 500 ms - - unsigned dcc; - dcc = (value >> 4) & 0x07; - if ((dcc & 0x06) == 0x06) { - BX_INFO(("CRA: divider chain RESET")); - } else if (dcc != 0x02) { - BX_PANIC(("CRA: divider chain control 0x%02x", dcc)); - } - BX_CMOS_THIS s.reg[REG_STAT_A] &= 0x80; - BX_CMOS_THIS s.reg[REG_STAT_A] |= (value & 0x7f); - BX_CMOS_THIS CRA_change(); - return; - break; - - case REG_STAT_B: // Control Register B - // bit 0: Daylight Savings Enable - // 1 = enable daylight savings - // 0 = disable daylight savings - // bit 1: 24/12 houre mode - // 1 = 24 hour format - // 0 = 12 hour format - // bit 2: Data Mode - // 1 = binary format - // 0 = BCD format - // bit 3: "square wave enable" - // Not supported and always read as 0 - // bit 4: Update Ended Interrupt Enable - // 1 = enable generation of update ended interrupt - // 0 = disable - // bit 5: Alarm Interrupt Enable - // 1 = enable generation of alarm interrupt - // 0 = disable - // bit 6: Periodic Interrupt Enable - // 1 = enable generation of periodic interrupt - // 0 = disable - // bit 7: Set mode - // 1 = user copy of time is "frozen" allowing time registers - // to be accessed without regard for an occurance of an update - // 0 = time updates occur normally - - // can not handle binary or 12-hour mode yet. - if (value & 0x04) - BX_PANIC(("write status reg B, binary format enabled.")); - if ( !(value & 0x02) ) - BX_PANIC(("write status reg B, 12 hour mode enabled.")); - - value &= 0xf7; // bit3 always 0 - // Note: setting bit 7 clears bit 4 - if (value & 0x80) - value &= 0xef; - - unsigned prev_CRB; - prev_CRB = BX_CMOS_THIS s.reg[REG_STAT_B]; - BX_CMOS_THIS s.reg[REG_STAT_B] = value; - if ( (prev_CRB & 0x40) != (value & 0x40) ) { - // Periodic Interrupt Enabled changed - if (prev_CRB & 0x40) { - // transition from 1 to 0, deactivate timer - bx_pc_system.deactivate_timer( - BX_CMOS_THIS s.periodic_timer_index); - } - else { - // transition from 0 to 1 - // if rate select is not 0, activate timer - if ( (BX_CMOS_THIS s.reg[REG_STAT_A] & 0x0f) != 0 ) { - bx_pc_system.activate_timer( - BX_CMOS_THIS s.periodic_timer_index, - BX_CMOS_THIS s.periodic_interval_usec, 1); - } - } - } - if ( (prev_CRB >= 0x80) && (value < 0x80) && BX_CMOS_THIS s.timeval_change) { - update_timeval(); - BX_CMOS_THIS s.timeval_change = 0; - } - return; - break; - - case REG_STAT_C: // Control Register C - case REG_STAT_D: // Control Register D - BX_ERROR(("write to control register 0x%02x (read-only)", - BX_CMOS_THIS s.cmos_mem_address)); - break; - - case REG_DIAGNOSTIC_STATUS: - BX_DEBUG(("write register 0x0e: 0x%02x", (unsigned) value)); - break; - - case REG_SHUTDOWN_STATUS: - switch (value) { - case 0x00: /* proceed with normal POST (soft reset) */ - BX_DEBUG(("Reg 0Fh(00): shutdown action = normal POST")); - break; - case 0x01: /* shutdown after memory size check */ - BX_DEBUG(("Reg 0Fh(01): request to change shutdown action" - " to shutdown after memory size check")); - case 0x02: /* shutdown after successful memory test */ - BX_DEBUG(("Reg 0Fh(02): request to change shutdown action" - " to shutdown after successful memory test")); - break; - case 0x03: /* shutdown after failed memory test */ - BX_DEBUG(("Reg 0Fh(03): request to change shutdown action" - " to shutdown after successful memory test")); - break; - case 0x04: /* jump to disk bootstrap routine */ - BX_DEBUG(("Reg 0Fh(04): request to change shutdown action " - "to jump to disk bootstrap routine.")); - break; - case 0x05: /* flush keyboard (issue EOI) and jump via 40h:0067h */ - BX_DEBUG(("Reg 0Fh(05): request to change shutdown action " - "to flush keyboard (issue EOI) and jump via 40h:0067h.")); - break; - case 0x06: - BX_DEBUG(("Reg 0Fh(06): Shutdown after memory test !")); - break; - case 0x07: /* reset (after failed test in virtual mode) */ - BX_DEBUG(("Reg 0Fh(07): request to change shutdown action " - "to reset (after failed test in virtual mode).")); - break; - case 0x08: /* used by POST during protected-mode RAM test (return to POST) */ - BX_DEBUG(("Reg 0Fh(08): request to change shutdown action " - "to return to POST (used by POST during protected-mode RAM test).")); - break; - case 0x09: /* return to BIOS extended memory block move - (interrupt 15h, func 87h was in progress) */ - BX_DEBUG(("Reg 0Fh(09): request to change shutdown action " - "to return to BIOS extended memory block move.")); - break; - case 0x0a: /* jump to DWORD pointer at 40:67 */ - BX_DEBUG(("Reg 0Fh(0a): request to change shutdown action" - " to jump to DWORD at 40:67")); - break; - case 0x0b: /* iret to DWORD pointer at 40:67 */ - BX_DEBUG(("Reg 0Fh(0b): request to change shutdown action" - " to iret to DWORD at 40:67")); - break; - case 0x0c: /* retf to DWORD pointer at 40:67 */ - BX_DEBUG(("Reg 0Fh(0c): request to change shutdown action" - " to retf to DWORD at 40:67")); - break; - default: - BX_PANIC(("unsupported cmos io write to reg F, case 0x%02x!", - (unsigned) value)); - break; - } - break; - - default: - BX_DEBUG(("write reg 0x%02x: value = 0x%02x", - (unsigned) BX_CMOS_THIS s.cmos_mem_address, (unsigned) value)); - break; - } - - BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address] = value; - break; - } -} - - - void -bx_cmos_c::checksum_cmos(void) -{ - unsigned i; - Bit16u sum; - - sum = 0; - for (i=0x10; i<=0x2d; i++) { - sum += BX_CMOS_THIS s.reg[i]; - } - BX_CMOS_THIS s.reg[REG_CSUM_HIGH] = (sum >> 8) & 0xff; /* checksum high */ - BX_CMOS_THIS s.reg[REG_CSUM_LOW] = (sum & 0xff); /* checksum low */ -} - - void -bx_cmos_c::periodic_timer_handler(void *this_ptr) -{ - bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr; - - class_ptr->periodic_timer(); -} - - void -bx_cmos_c::periodic_timer() -{ - // if periodic interrupts are enabled, trip IRQ 8, and - // update status register C - if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x40) { - BX_CMOS_THIS s.reg[REG_STAT_C] |= 0xc0; // Interrupt Request, Periodic Int - DEV_pic_raise_irq(8); - } -} - - void -bx_cmos_c::one_second_timer_handler(void *this_ptr) -{ - bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr; - - class_ptr->one_second_timer(); -} - - void -bx_cmos_c::one_second_timer() -{ - // divider chain reset - RTC stopped - if ((BX_CMOS_THIS s.reg[REG_STAT_A] & 0x60) == 0x60) - return; - - // update internal time/date buffer - BX_CMOS_THIS s.timeval++; - - // Dont update CMOS user copy of time/date if CRB bit7 is 1 - // Nothing else do to - if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x80) - return; - - BX_CMOS_THIS s.reg[REG_STAT_A] |= 0x80; // set UIP bit - - // UIP timer for updating clock & alarm functions - bx_pc_system.activate_timer(BX_CMOS_THIS s.uip_timer_index, - 244, 0); -} - - void -bx_cmos_c::uip_timer_handler(void *this_ptr) -{ - bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr; - - class_ptr->uip_timer(); -} - - void -bx_cmos_c::uip_timer() -{ - update_clock(); - - // if update interrupts are enabled, trip IRQ 8, and - // update status register C - if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x10) { - BX_CMOS_THIS s.reg[REG_STAT_C] |= 0x90; // Interrupt Request, Update Ended - DEV_pic_raise_irq(8); - } - - // compare CMOS user copy of time/date to alarm time/date here - if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x20) { - // Alarm interrupts enabled - bx_bool alarm_match = 1; - if ( (BX_CMOS_THIS s.reg[REG_SEC_ALARM] & 0xc0) != 0xc0 ) { - // seconds alarm not in dont care mode - if (BX_CMOS_THIS s.reg[REG_SEC] != BX_CMOS_THIS s.reg[REG_SEC_ALARM]) - alarm_match = 0; - } - if ( (BX_CMOS_THIS s.reg[REG_MIN_ALARM] & 0xc0) != 0xc0 ) { - // minutes alarm not in dont care mode - if (BX_CMOS_THIS s.reg[REG_MIN] != BX_CMOS_THIS s.reg[REG_MIN_ALARM]) - alarm_match = 0; - } - if ( (BX_CMOS_THIS s.reg[REG_HOUR_ALARM] & 0xc0) != 0xc0 ) { - // hours alarm not in dont care mode - if (BX_CMOS_THIS s.reg[REG_HOUR] != BX_CMOS_THIS s.reg[REG_HOUR_ALARM]) - alarm_match = 0; - } - if (alarm_match) { - BX_CMOS_THIS s.reg[REG_STAT_C] |= 0xa0; // Interrupt Request, Alarm Int - DEV_pic_raise_irq(8); - } - } - BX_CMOS_THIS s.reg[REG_STAT_A] &= 0x7f; // clear UIP bit -} - - - void -bx_cmos_c::update_clock() -{ - struct tm *time_calendar; - unsigned year, month, day, century; - Bit8u val_bcd; - - time_calendar = localtime(& BX_CMOS_THIS s.timeval); - - // update seconds - val_bcd = - ((time_calendar->tm_sec / 10) << 4) | - (time_calendar->tm_sec % 10); - BX_CMOS_THIS s.reg[REG_SEC] = val_bcd; - - // update minutes - val_bcd = - ((time_calendar->tm_min / 10) << 4) | - (time_calendar->tm_min % 10); - BX_CMOS_THIS s.reg[REG_MIN] = val_bcd; - - // update hours - val_bcd = - ((time_calendar->tm_hour / 10) << 4) | - (time_calendar->tm_hour % 10); - BX_CMOS_THIS s.reg[REG_HOUR] = val_bcd; - - // update day of the week - day = time_calendar->tm_wday + 1; // 0..6 to 1..7 - BX_CMOS_THIS s.reg[REG_WEEK_DAY] = ((day / 10) << 4) | (day % 10); - - // update day of the month - day = time_calendar->tm_mday; - BX_CMOS_THIS s.reg[REG_MONTH_DAY] = ((day / 10) << 4) | (day % 10); - - // update month - month = time_calendar->tm_mon + 1; - BX_CMOS_THIS s.reg[REG_MONTH] = ((month / 10) << 4) | (month % 10); - - // update year - year = time_calendar->tm_year % 100; - BX_CMOS_THIS s.reg[REG_YEAR] = ((year / 10) << 4) | (year % 10); - - // update century - century = (time_calendar->tm_year / 100) + 19; - BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE] = - ((century / 10) << 4) | (century % 10); - - // Raul Hudea pointed out that some bioses also use reg 0x37 for the - // century byte. Tony Heller says this is critical in getting WinXP to run. - BX_CMOS_THIS s.reg[REG_IBM_PS2_CENTURY_BYTE] = - BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE]; -} - - void -bx_cmos_c::update_timeval() -{ - struct tm time_calendar; - Bit8u val_bin; - - // update seconds - val_bin = - ((BX_CMOS_THIS s.reg[REG_SEC] >> 4) * 10) + - (BX_CMOS_THIS s.reg[REG_SEC] & 0x0f); - time_calendar.tm_sec = val_bin; - - // update minutes - val_bin = - ((BX_CMOS_THIS s.reg[REG_MIN] >> 4) * 10) + - (BX_CMOS_THIS s.reg[REG_MIN] & 0x0f); - time_calendar.tm_min = val_bin; - - // update hours - val_bin = - ((BX_CMOS_THIS s.reg[REG_HOUR] >> 4) * 10) + - (BX_CMOS_THIS s.reg[REG_HOUR] & 0x0f); - time_calendar.tm_hour = val_bin; - - // update day of the month - val_bin = - ((BX_CMOS_THIS s.reg[REG_MONTH_DAY] >> 4) * 10) + - (BX_CMOS_THIS s.reg[REG_MONTH_DAY] & 0x0f); - time_calendar.tm_mday = val_bin; - - // update month - val_bin = - ((BX_CMOS_THIS s.reg[REG_MONTH] >> 4) * 10) + - (BX_CMOS_THIS s.reg[REG_MONTH] & 0x0f); - time_calendar.tm_mon = val_bin - 1; - - // update year - val_bin = - ((BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE] >> 4) * 10) + - (BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE] & 0x0f); - val_bin = (val_bin - 19) * 100; - val_bin += - (((BX_CMOS_THIS s.reg[REG_YEAR] >> 4) * 10) + - (BX_CMOS_THIS s.reg[REG_YEAR] & 0x0f)); - time_calendar.tm_year = val_bin; - - BX_CMOS_THIS s.timeval = mktime(& time_calendar); -} diff --git a/tools/ioemu/iodev/cmos.h b/tools/ioemu/iodev/cmos.h deleted file mode 100644 index c53907db3e..0000000000 --- a/tools/ioemu/iodev/cmos.h +++ /dev/null @@ -1,90 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: cmos.h,v 1.9 2003/01/04 00:02:07 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - - - -#if BX_USE_CMOS_SMF -# define BX_CMOS_SMF static -# define BX_CMOS_THIS theCmosDevice-> -#else -# define BX_CMOS_SMF -# define BX_CMOS_THIS this-> -#endif - - -class bx_cmos_c : public bx_cmos_stub_c { -public: - bx_cmos_c(void); - ~bx_cmos_c(void); - - virtual void init(void); - virtual void checksum_cmos(void); - virtual void reset(unsigned type); - - virtual Bit32u get_reg(unsigned reg) { - return s.reg[reg]; - } - virtual void set_reg(unsigned reg, Bit32u val) { - s.reg[reg] = val; - } - virtual time_t get_timeval() { - return s.timeval; - } - - struct { - int periodic_timer_index; - Bit32u periodic_interval_usec; - int one_second_timer_index; - int uip_timer_index; - time_t timeval; - Bit8u cmos_mem_address; - bx_bool timeval_change; - - Bit8u reg[BX_NUM_CMOS_REGS]; - } s; // state information - -private: - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); -#if !BX_USE_CMOS_SMF - Bit32u read(Bit32u address, unsigned io_len); - void write(Bit32u address, Bit32u value, unsigned len); -#endif - -public: - static void periodic_timer_handler(void *); - static void one_second_timer_handler(void *); - static void uip_timer_handler(void *); - BX_CMOS_SMF void periodic_timer(void); - BX_CMOS_SMF void one_second_timer(void); - BX_CMOS_SMF void uip_timer(void); -private: - BX_CMOS_SMF void update_clock(void); - BX_CMOS_SMF void update_timeval(void); - BX_CMOS_SMF void CRA_change(void); - }; diff --git a/tools/ioemu/iodev/cpu.cc b/tools/ioemu/iodev/cpu.cc deleted file mode 100644 index 3e234d5cc8..0000000000 --- a/tools/ioemu/iodev/cpu.cc +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Main cpu loop for handling I/O requests coming from a virtual machine - * Copyright © 2004, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU Lesser General Public License, - * version 2.1, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "bochs.h" -#include -#ifdef BX_USE_VMX -#include -/* According to POSIX 1003.1-2001 */ -#include - -/* According to earlier standards */ -#include -#include -#include -#include -#endif - -#define LOG_THIS BX_CPU_THIS_PTR - -#ifdef BX_USE_VMX - -//the evtchn fd for polling -int evtchn_fd = -1; -//the evtchn port for polling the notification, should be inputed as bochs's parameter -u16 ioreq_port = 0; - -void *shared_page = NULL; - -//some functions to handle the io req packet - -//get the ioreq packets from share mem -ioreq_t* bx_cpu_c::__get_ioreq(void) -{ - ioreq_t *req; - req = &((vcpu_iodata_t *) shared_page)->vp_ioreq; - if (req->state == STATE_IOREQ_READY) { - req->state = STATE_IOREQ_INPROCESS; - } else { - BX_INFO(("False I/O request ... in-service already: %lx, pvalid: %lx,port: %lx, data: %lx, count: %lx, size: %lx\n", req->state, req->pdata_valid, req->addr, req->u.data, req->count, req->size)); - req = NULL; - } - - return req; -} - -//use poll to get the port notification -//ioreq_vec--out,the -//retval--the number of ioreq packet -ioreq_t* bx_cpu_c::get_ioreq(void) -{ - ioreq_t *req; - int rc; - u16 buf[2]; - rc = read(evtchn_fd, buf, 2); - if (rc == 2 && buf[0] == ioreq_port){//got only one matched 16bit port index - // unmask the wanted port again - write(evtchn_fd, &ioreq_port, 2); - - //get the io packet from shared memory - return __get_ioreq(); - } - - //read error or read nothing - return NULL; -} - -//send the ioreq to device model -void bx_cpu_c::dispatch_ioreq(ioreq_t *req) -{ - int ret, i; - int sign; - - sign = (req->df) ? -1 : 1; - - if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) { - if (req->size != 4) { - // Bochs expects higher bits to be 0 - req->u.data &= (1UL << (8 * req->size))-1; - } - } - if (req->port_mm == 0){//port io - if(req->dir == IOREQ_READ){//read - //BX_INFO(("pio: addr:%llx, value:%llx, size: %llx, count: %llx\n", req->addr, req->u.data, req->size, req->count)); - - if (!req->pdata_valid) - req->u.data = BX_INP(req->addr, req->size); - else { - unsigned long tmp; - - for (i = 0; i < req->count; i++) { - tmp = BX_INP(req->addr, req->size); - BX_MEM_WRITE_PHYSICAL((dma_addr_t) req->u.pdata + (sign * i * req->size), - req->size, &tmp); - } - } - } else if(req->dir == IOREQ_WRITE) { - //BX_INFO(("pio: addr:%llx, value:%llx, size: %llx, count: %llx\n", req->addr, req->u.data, req->size, req->count)); - - if (!req->pdata_valid) { - BX_OUTP(req->addr, (dma_addr_t) req->u.data, req->size); - } else { - for (i = 0; i < req->count; i++) { - unsigned long tmp; - - BX_MEM_READ_PHYSICAL((dma_addr_t) req->u.pdata + (sign * i * req->size), req->size, - &tmp); - BX_OUTP(req->addr, (dma_addr_t) tmp, req->size); - } - } - - } - } else if (req->port_mm == 1){//memory map io - if (!req->pdata_valid) { - if(req->dir == IOREQ_READ){//read - //BX_INFO(("mmio[value]: addr:%llx, value:%llx, size: %llx, count: %llx\n", req->addr, req->u.data, req->size, req->count)); - for (i = 0; i < req->count; i++) { - BX_MEM_READ_PHYSICAL(req->addr + (sign * i * req->size), req->size, &req->u.data); - } - } else if(req->dir == IOREQ_WRITE) {//write - //BX_INFO(("mmio[value]: addr:%llx, value:%llx, size: %llx, count: %llx\n", req->addr, req->u.data, req->size, req->count)); - for (i = 0; i < req->count; i++) { - BX_MEM_WRITE_PHYSICAL(req->addr + (sign * i * req->size), req->size, &req->u.data); - } - } - } else { - //handle movs - unsigned long tmp; - if (req->dir == IOREQ_READ) { - //BX_INFO(("mmio[pdata]: addr:%llx, pdata:%llx, size: %x, count: %x\n", req->addr, req->u.pdata, req->size, req->count)); - for (i = 0; i < req->count; i++) { - BX_MEM_READ_PHYSICAL(req->addr + (sign * i * req->size), req->size, &tmp); - BX_MEM_WRITE_PHYSICAL((dma_addr_t) req->u.pdata + (sign * i * req->size), req->size, &tmp); - } - } else if (req->dir == IOREQ_WRITE) { - //BX_INFO(("mmio[pdata]: addr:%llx, pdata:%llx, size: %x, count: %x\n", req->addr, req->u.pdata, req->size, req->count)); - for (i = 0; i < req->count; i++) { - BX_MEM_READ_PHYSICAL((dma_addr_t)req->u.pdata + (sign * i * req->size), req->size, &tmp); - BX_MEM_WRITE_PHYSICAL(req->addr + (sign * i * req->size), req->size, &tmp); - } - } - } - } - - /* No state change if state = STATE_IORESP_HOOK */ - if (req->state == STATE_IOREQ_INPROCESS) - req->state = STATE_IORESP_READY; - - send_event = 1; -} - -void -bx_cpu_c::handle_ioreq(void) -{ - ioreq_t *req = get_ioreq(); - if (req) - dispatch_ioreq(req); -} - -void -bx_cpu_c::timer_handler(void) -{ - handle_ioreq(); -} - -#endif - -#define rdtscl(low) \ - __asm__ __volatile__("rdtsc" : "=a" (low) : : "edx") - -void -bx_cpu_c::cpu_loop(int max_instr_count) -{ - Bit8u vector; - fd_set rfds; - unsigned long stime_usec; - struct timeval tv; - int retval; - - /* Watch stdin (fd 0) to see when it has input. */ - FD_ZERO(&rfds); - - while (1) { - static unsigned long long t1 = 0; - unsigned long long t2; - - /* Wait up to one seconds. */ - tv.tv_sec = 0; - tv.tv_usec = 100000; - FD_SET(evtchn_fd, &rfds); - - send_event = 0; - - if (t1 == 0) // the first time - rdtscll(t1); - - retval = select(evtchn_fd+1, &rfds, NULL, NULL, &tv); - if (retval == -1) { - perror("select"); - return; - } - - rdtscll(t2); - -#if __WORDSIZE == 32 -#define ULONGLONG_MAX 0xffffffffffffffffULL -#else -#define ULONGLONG_MAX ULONG_MAX -#endif - - if (t2 <= t1) - BX_TICKN((t2 + ULONGLONG_MAX - t1) / tsc_per_bx_tick); - else - BX_TICKN((t2 - t1) / tsc_per_bx_tick); - t1 = t2; - - timer_handler(); - if (BX_CPU_INTR) { -#if BX_SUPPORT_APIC - if (BX_CPU_THIS_PTR local_apic.INTR) - vector = BX_CPU_THIS_PTR local_apic.acknowledge_int (); - else - vector = DEV_pic_iac(); // may set INTR with next interrupt -#else - // if no local APIC, always acknowledge the PIC. - vector = DEV_pic_iac(); // may set INTR with next interrupt -#endif - interrupt(vector); - } - /* we check DMA after interrupt check*/ - while(BX_HRQ){ - DEV_dma_raise_hlda(); - } - - if (send_event) { - int ret; - ret = xc_evtchn_send(xc_handle, ioreq_port); - if (ret == -1) { - BX_ERROR(("evtchn_send failed on port: %d\n", ioreq_port)); - } - } - } -} - -#ifdef __i386__ -static __inline__ void set_bit(long nr, volatile void *addr) -{ - __asm__ __volatile__( "lock ; " - "btsl %1,%0" - :"=m" ((*(volatile long *)addr)) - :"Ir" (nr)); - - return; -} -#else -/* XXX: clean for IPF */ -static __inline__ void set_bit(long nr, volatile void *addr) -{ - __asm__ __volatile__( "lock ; " - "btsq %1,%0" - :"=m" ((*(volatile long *)addr)) - :"Ir" (nr)); - - return; -} -#endif - -void -bx_cpu_c::interrupt(Bit8u vector) -{ - unsigned long *intr, tscl; - int ret; - - // Send a message on the event channel. Add the vector to the shared mem - // page. - - rdtscl(tscl); - BX_DEBUG(("%lx: injecting vector: %x\n", tscl, vector)); - intr = &(((vcpu_iodata_t *) shared_page)->vp_intr[0]); - set_bit(vector, intr); - - send_event = 1; -} - -void -bx_cpu_c::init(bx_mem_c*) -{ -#ifdef BX_USE_VMX - if (evtchn_fd != -1)//the evtchn has been opened by another cpu object - return; - - //use nonblock reading not polling, may change in future. - evtchn_fd = open("/dev/xen/evtchn", O_RDWR|O_NONBLOCK); - if (evtchn_fd == -1) { - perror("open"); - return; - } - - BX_INFO(("listening to port: %d\n", ioreq_port)); - /*unmask the wanted port -- bind*/ - if (ioctl(evtchn_fd, ('E'<<8)|2, ioreq_port) == -1) { - perror("ioctl"); - return; - } - -#if 0 - //register the reading evtchn function as timer - bx_pc_system.register_timer(this, timer_handler, 1000,//1000 us, may change - 1,//continuous timer - 1,//active - "cpu reading evtchn handler"); -#endif - -#endif -} - -void -bx_cpu_c::reset(unsigned) -{ -} - -void -bx_cpu_c::atexit() -{ -} - -void -bx_cpu_c::set_INTR(unsigned value) -{ - BX_CPU_THIS_PTR INTR = value; -} - -void -bx_cpu_c::pagingA20Changed() -{ -} - -bx_cpu_c::bx_cpu_c() -{ -} - -bx_cpu_c::~bx_cpu_c() -{ -} diff --git a/tools/ioemu/iodev/crc32.cc b/tools/ioemu/iodev/crc32.cc deleted file mode 100644 index a20abaaf82..0000000000 --- a/tools/ioemu/iodev/crc32.cc +++ /dev/null @@ -1,49 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: crc32.cc,v 1.4 2001/10/03 13:10:38 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -/* CRC-32 calculator - * Adapted from http://www.createwindow.org/programming/crc32/ - */ - -#include "crc32.h" - -CRC_Generator::CRC_Generator() { - init(); -} - -void CRC_Generator::init(void) { - Bit32u POLYNOMIAL = 0x04c11db7; - int i; - - for(i = 0; i<0xFF; i++) { - int j; - crc32_table[i]=reflect(i,8) << 24; - for(j=0; j<8; j++) - crc32_table[i] = (crc32_table[i]<<1)^(crc32_table[i] & (1<<31) ? POLYNOMIAL : 0); - crc32_table[i] = reflect(crc32_table[i], 32); - } -} - -Bit32u CRC_Generator::reflect(Bit32u ref, Bit8u ch) { - Bit32u value(0); - int i; - - for(i=1; i<(ch+1); i++) { - if(ref & 1) - value |= 1 << (ch-i); - ref >>= 1; - } - return value; -} - -Bit32u CRC_Generator::get_CRC(Bit8u * buf, Bit32u buflen) { - Bit32u ulCRC(0xFFFFFFFF); - Bit32u len(buflen); - Bit8u * buffer=(Bit8u *) buf; - - while(len--) - ulCRC=(ulCRC>>8)^crc32_table[(ulCRC & 0xFF)^*buffer++]; - return ulCRC ^ 0xFFFFFFFF; -} - diff --git a/tools/ioemu/iodev/crc32.h b/tools/ioemu/iodev/crc32.h deleted file mode 100644 index faedaf840b..0000000000 --- a/tools/ioemu/iodev/crc32.h +++ /dev/null @@ -1,25 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: crc32.h,v 1.3 2001/10/03 13:10:38 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -/* CRC-32 calculator - * Adapted from http://www.createwindow.org/programming/crc32/ - */ - -#ifndef _CRC_32_H_ -#define _CRC_32_H_ - -#include "bochs.h" - -class CRC_Generator { -private: - Bit32u crc32_table[256]; - Bit32u reflect(Bit32u ref, Bit8u ch); -public: - void init(void); - CRC_Generator(); - Bit32u get_CRC(Bit8u * buf, Bit32u buflen); -}; - -#endif //_CRC_32_H_ - diff --git a/tools/ioemu/iodev/devices.cc b/tools/ioemu/iodev/devices.cc deleted file mode 100644 index 5dd7f5daa3..0000000000 --- a/tools/ioemu/iodev/devices.cc +++ /dev/null @@ -1,685 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: devices.cc,v 1.58 2003/12/26 13:53:39 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -#include "bochs.h" -#define LOG_THIS bx_devices. - - - -/* main memory size (in Kbytes) - * subtract 1k for extended BIOS area - * report only base memory, not extended mem - */ -#define BASE_MEMORY_IN_K 640 - - -bx_devices_c bx_devices; - - - - -// constructor for bx_devices_c -bx_devices_c::bx_devices_c(void) -{ - put("DEV"); - settype(DEVLOG); - -#if BX_PCI_SUPPORT - pluginPciBridge = &stubPci; - pluginPci2IsaBridge = NULL; -#if BX_PCI_VGA_SUPPORT - pluginPciVgaAdapter = NULL; -#endif -#if BX_PCI_USB_SUPPORT - pluginPciUSBAdapter = NULL; -#endif -#endif - pit = NULL; - pluginKeyboard = &stubKeyboard; - pluginDmaDevice = &stubDma; - pluginFloppyDevice = &stubFloppy; - pluginBiosDevice = NULL; - pluginCmosDevice = &stubCmos; - pluginSerialDevice = NULL; - pluginParallelDevice = NULL; - pluginUnmapped = NULL; - pluginVgaDevice = &stubVga; - pluginPicDevice = &stubPic; - pluginHardDrive = &stubHardDrive; - pluginSB16Device = NULL; - pluginNE2kDevice =&stubNE2k; - pluginExtFpuIrq = NULL; - pluginGameport = NULL; - g2h = NULL; -#if BX_IODEBUG_SUPPORT - iodebug = NULL; -#endif -} - - -bx_devices_c::~bx_devices_c(void) -{ - // nothing needed for now - BX_DEBUG(("Exit.")); - timer_handle = BX_NULL_TIMER_HANDLE; -} - - - void -bx_devices_c::init(BX_MEM_C *newmem) -{ - unsigned i; - - BX_DEBUG(("Init $Id: devices.cc,v 1.58 2003/12/26 13:53:39 vruppert Exp $")); - mem = newmem; - - /* no read / write handlers defined */ - num_read_handles = 0; - num_write_handles = 0; - - /* set unused elements to appropriate values */ - for (i=0; i < BX_MAX_IO_DEVICES; i++) { - io_read_handler[i].funct = NULL; - io_write_handler[i].funct = NULL; - } - - /* set no-default handlers, will be overwritten by the real default handler */ - io_read_handler[BX_DEFAULT_IO_DEVICE].handler_name = "Default"; - io_read_handler[BX_DEFAULT_IO_DEVICE].funct = &default_read_handler; - io_read_handler[BX_DEFAULT_IO_DEVICE].this_ptr = NULL; - io_read_handler[BX_DEFAULT_IO_DEVICE].mask = 7; - io_write_handler[BX_DEFAULT_IO_DEVICE].handler_name = "Default"; - io_write_handler[BX_DEFAULT_IO_DEVICE].funct = &default_write_handler; - io_write_handler[BX_DEFAULT_IO_DEVICE].this_ptr = NULL; - io_write_handler[BX_DEFAULT_IO_DEVICE].mask = 7; - - /* set handlers to the default one */ - for (i=0; i < 0x10000; i++) { - read_handler_id[i] = BX_DEFAULT_IO_DEVICE; - write_handler_id[i] = BX_DEFAULT_IO_DEVICE; - } - - for (i=0; i < BX_MAX_IRQS; i++) { - irq_handler_name[i] = NULL; - } - - // BBD: At present, the only difference between "core" and "optional" - // plugins is that initialization and reset of optional plugins is handled - // by the plugin device list (). Init and reset of core plugins is done - // "by hand" in this file. Basically, we're using core plugins when we - // want to control the init order. - // - // CB: UNMAPPED and BIOSDEV should maybe be optional - PLUG_load_plugin(unmapped, PLUGTYPE_CORE); - PLUG_load_plugin(biosdev, PLUGTYPE_CORE); - PLUG_load_plugin(cmos, PLUGTYPE_CORE); - PLUG_load_plugin(dma, PLUGTYPE_CORE); - PLUG_load_plugin(pic, PLUGTYPE_CORE); - PLUG_load_plugin(vga, PLUGTYPE_CORE); - PLUG_load_plugin(floppy, PLUGTYPE_CORE); - PLUG_load_plugin(harddrv, PLUGTYPE_OPTIONAL); - PLUG_load_plugin(keyboard, PLUGTYPE_OPTIONAL); - if (is_serial_enabled ()) - PLUG_load_plugin(serial, PLUGTYPE_OPTIONAL); - if (is_parallel_enabled ()) - PLUG_load_plugin(parallel, PLUGTYPE_OPTIONAL); - PLUG_load_plugin(extfpuirq, PLUGTYPE_OPTIONAL); -#if BX_SUPPORT_GAME - PLUG_load_plugin(gameport, PLUGTYPE_OPTIONAL); -#endif - - // Start with registering the default (unmapped) handler - pluginUnmapped->init (); - - // PCI logic (i440FX) - if (bx_options.Oi440FXSupport->get ()) { -#if BX_PCI_SUPPORT - PLUG_load_plugin(pci, PLUGTYPE_OPTIONAL); - PLUG_load_plugin(pci2isa, PLUGTYPE_OPTIONAL); -#if BX_PCI_VGA_SUPPORT - PLUG_load_plugin(pcivga, PLUGTYPE_OPTIONAL); -#endif -#if BX_PCI_USB_SUPPORT - PLUG_load_plugin(pciusb, PLUGTYPE_OPTIONAL); -#endif -#else - BX_ERROR(("Bochs is not compiled with PCI support")); -#endif - } - -#if BX_SUPPORT_APIC - // I/O APIC 82093AA - ioapic = & bx_ioapic; - ioapic->init (); -#endif - - // BIOS log - pluginBiosDevice->init (); - - // CMOS RAM & RTC - pluginCmosDevice->init (); - - /*--- 8237 DMA ---*/ - pluginDmaDevice->init(); - - //--- FLOPPY --- - pluginFloppyDevice->init(); - - //--- SOUND --- - if (bx_options.sb16.Opresent->get ()) { -#if BX_SUPPORT_SB16 - PLUG_load_plugin(sb16, PLUGTYPE_OPTIONAL); -#else - BX_ERROR(("Bochs is not compiled with SB16 support")); -#endif - } - - /*--- VGA adapter ---*/ - pluginVgaDevice->init (); - - /*--- 8259A PIC ---*/ - pluginPicDevice->init(); - - /*--- 8254 PIT ---*/ - pit = & bx_pit; - pit->init(); - - bx_virt_timer.init(); - - bx_slowdown_timer.init(); - -#if BX_IODEBUG_SUPPORT - iodebug = &bx_iodebug; - iodebug->init(); -#endif - - // NE2000 NIC - if (bx_options.ne2k.Opresent->get ()) { -#if BX_NE2K_SUPPORT - PLUG_load_plugin(ne2k, PLUGTYPE_OPTIONAL); -#else - BX_ERROR(("Bochs is not compiled with NE2K support")); -#endif - } - -#if 0 - // Guest to Host interface. Used with special guest drivers - // which move data to/from the host environment. - g2h = &bx_g2h; - g2h->init(); -#endif - - // system hardware - register_io_read_handler( this, - &read_handler, - 0x0092, - "Port 92h System Control", 1 ); - register_io_write_handler(this, - &write_handler, - 0x0092, - "Port 92h System Control", 1 ); - - // misc. CMOS - Bit32u extended_memory_in_k = mem->get_memory_in_k() > 1024 ? (mem->get_memory_in_k() - 1024) : 0; - if (extended_memory_in_k > 0xffff) extended_memory_in_k = 0xffff; - - DEV_cmos_set_reg(0x15, (Bit8u) BASE_MEMORY_IN_K); - DEV_cmos_set_reg(0x16, (Bit8u) (BASE_MEMORY_IN_K >> 8)); - DEV_cmos_set_reg(0x17, (Bit8u) (extended_memory_in_k & 0xff) ); - DEV_cmos_set_reg(0x18, (Bit8u) ((extended_memory_in_k >> 8) & 0xff) ); - DEV_cmos_set_reg(0x30, (Bit8u) (extended_memory_in_k & 0xff) ); - DEV_cmos_set_reg(0x31, (Bit8u) ((extended_memory_in_k >> 8) & 0xff) ); - - Bit32u extended_memory_in_64k = mem->get_memory_in_k() > 16384 ? (mem->get_memory_in_k() - 16384) / 64 : 0; - if (extended_memory_in_64k > 0xffff) extended_memory_in_64k = 0xffff; - - DEV_cmos_set_reg(0x34, (Bit8u) (extended_memory_in_64k & 0xff) ); - DEV_cmos_set_reg(0x35, (Bit8u) ((extended_memory_in_64k >> 8) & 0xff) ); - - if (timer_handle != BX_NULL_TIMER_HANDLE) { - timer_handle = bx_pc_system.register_timer( this, timer_handler, - (unsigned) BX_IODEV_HANDLER_PERIOD, 1, 1, "devices.cc"); - } - - // Clear fields for bulk IO acceleration transfers. - bulkIOHostAddr = 0; - bulkIOQuantumsRequested = 0; - bulkIOQuantumsTransferred = 0; - - bx_init_plugins(); - - /* now perform checksum of CMOS memory */ - DEV_cmos_checksum(); -} - - - void -bx_devices_c::reset(unsigned type) -{ - pluginUnmapped->reset(type); -#if BX_PCI_SUPPORT - if (bx_options.Oi440FXSupport->get ()) { - pluginPciBridge->reset(type); - pluginPci2IsaBridge->reset(type); -#if BX_PCI_VGA_SUPPORT - pluginPciVgaAdapter->reset(type); -#endif -#if BX_PCI_USB_SUPPORT - pluginPciUSBAdapter->reset(type); -#endif - } -#endif -#if BX_SUPPORT_IOAPIC - ioapic->reset (type); -#endif - pluginBiosDevice->reset(type); - pluginCmosDevice->reset(type); - pluginDmaDevice->reset(type); - pluginFloppyDevice->reset(type); -#if BX_SUPPORT_SB16 - if (pluginSB16Device) pluginSB16Device->reset(type); -#endif - pluginVgaDevice->reset(type); - pluginPicDevice->reset(type); - pit->reset(type); - bx_slowdown_timer.reset(type); -#if BX_IODEBUG_SUPPORT - iodebug->reset(type); -#endif -#if BX_NE2K_SUPPORT - if (pluginNE2kDevice) pluginNE2kDevice->reset(type); -#endif - - bx_reset_plugins(type); -} - - - Bit32u -bx_devices_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_DEV_SMF - bx_devices_c *class_ptr = (bx_devices_c *) this_ptr; - - return( class_ptr->port92_read(address, io_len) ); -} - - - Bit32u -bx_devices_c::port92_read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_DEV_SMF - - BX_DEBUG(("port92h read partially supported!!!")); - BX_DEBUG((" returning %02x", (unsigned) (BX_GET_ENABLE_A20() << 1))); - return(BX_GET_ENABLE_A20() << 1); -} - - - void -bx_devices_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_DEV_SMF - bx_devices_c *class_ptr = (bx_devices_c *) this_ptr; - - class_ptr->port92_write(address, value, io_len); -} - - void -bx_devices_c::port92_write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_DEV_SMF - bx_bool bx_cpu_reset; - - BX_DEBUG(("port92h write of %02x partially supported!!!", - (unsigned) value)); - BX_DEBUG(("A20: set_enable_a20() called")); - BX_SET_ENABLE_A20( (value & 0x02) >> 1 ); - BX_DEBUG(("A20: now %u", (unsigned) BX_GET_ENABLE_A20())); - bx_cpu_reset = (value & 0x01); /* high speed reset */ - if (bx_cpu_reset) { - BX_PANIC(("PORT 92h write: CPU reset requested!")); - } -} - - -// This defines a no-default read handler, -// so Bochs does not segfault if unmapped is not loaded - Bit32u -bx_devices_c::default_read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ - UNUSED(this_ptr); - BX_PANIC(("No default io-read handler found for 0x%04x/%d. Unmapped io-device not loaded ?", address, io_len)); - return 0xffffffff; -} - -// This defines a no-default write handler, -// so Bochs does not segfault if unmapped is not loaded - void -bx_devices_c::default_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ - UNUSED(this_ptr); - BX_PANIC(("No default io-write handler found for 0x%04x/%d. Unmapped io-device not loaded ?", address, io_len)); -} - - void -bx_devices_c::timer_handler(void *this_ptr) -{ - bx_devices_c *class_ptr = (bx_devices_c *) this_ptr; - - class_ptr->timer(); -} - - void -bx_devices_c::timer() -{ -#if (BX_USE_NEW_PIT==0) - if ( pit->periodic( BX_IODEV_HANDLER_PERIOD ) ) { - // This is a hack to make the IRQ0 work - DEV_pic_lower_irq(0); - DEV_pic_raise_irq(0); - } -#endif - - - // separate calls to bx_gui->handle_events from the keyboard code. - { - static int multiple=0; - if ( ++multiple==10) - { - multiple=0; - SIM->periodic (); - if (!BX_CPU(0)->kill_bochs_request) - bx_gui->handle_events(); - } - } - -// KPL Removed lapic periodic timer registration here. -} - - - bx_bool -bx_devices_c::register_irq(unsigned irq, const char *name) -{ - if (irq >= BX_MAX_IRQS) { - BX_PANIC(("IO device %s registered with IRQ=%d above %u", - name, irq, (unsigned) BX_MAX_IRQS-1)); - return false; - } - if (irq_handler_name[irq]) { - BX_PANIC(("IRQ %u conflict, %s with %s", irq, - irq_handler_name[irq], name)); - return false; - } - irq_handler_name[irq] = name; - return true; -} - - bx_bool -bx_devices_c::unregister_irq(unsigned irq, const char *name) -{ - if (irq >= BX_MAX_IRQS) { - BX_PANIC(("IO device %s tried to unregister IRQ %d above %u", - name, irq, (unsigned) BX_MAX_IRQS-1)); - return false; - } - - if (!irq_handler_name[irq]) { - BX_INFO(("IO device %s tried to unregister IRQ %d, not registered", - name, irq)); - return false; - } - - if (strcmp(irq_handler_name[irq], name)) { - BX_INFO(("IRQ %u not registered to %s but to %s", irq, - name, irq_handler_name[irq])); - return false; - } - irq_handler_name[irq] = NULL; - return true; -} - - bx_bool -bx_devices_c::register_io_read_handler( void *this_ptr, bx_read_handler_t f, - Bit32u addr, const char *name, Bit8u mask ) -{ - unsigned handle; - - addr &= 0x0000ffff; - - /* first find existing handle for function or create new one */ - for (handle=0; handle < num_read_handles; handle++) { - if ((io_read_handler[handle].funct == f) && - (io_read_handler[handle].mask == mask)) break; - } - - if (handle >= num_read_handles) { - /* no existing handle found, create new one */ - if (num_read_handles >= BX_DEFAULT_IO_DEVICE) { - BX_INFO(("too many IO devices installed.")); - BX_PANIC((" try increasing BX_MAX_IO_DEVICES")); - } - num_read_handles++; - io_read_handler[handle].funct = f; - io_read_handler[handle].this_ptr = this_ptr; - io_read_handler[handle].handler_name = name; - io_read_handler[handle].mask = mask; - } - - /* change table to reflect new handler id for that address */ - if (read_handler_id[addr] < BX_DEFAULT_IO_DEVICE) { - // another handler is already registered for that address - BX_ERROR(("IO device address conflict(read) at IO address %Xh", - (unsigned) addr)); - BX_ERROR((" conflicting devices: %s & %s", - io_read_handler[handle].handler_name, io_read_handler[read_handler_id[addr]].handler_name)); - return false; // address not available, return false. - } - read_handler_id[addr] = handle; - return true; // address mapped successfully -} - - - - bx_bool -bx_devices_c::register_io_write_handler( void *this_ptr, bx_write_handler_t f, - Bit32u addr, const char *name, Bit8u mask ) -{ - unsigned handle; - - addr &= 0x0000ffff; - - /* first find existing handle for function or create new one */ - for (handle=0; handle < num_write_handles; handle++) { - if ((io_write_handler[handle].funct == f) && - (io_write_handler[handle].mask == mask)) break; - } - - if (handle >= num_write_handles) { - /* no existing handle found, create new one */ - if (num_write_handles >= BX_DEFAULT_IO_DEVICE) { - BX_INFO(("too many IO devices installed.")); - BX_PANIC((" try increasing BX_MAX_IO_DEVICES")); - } - num_write_handles++; - io_write_handler[handle].funct = f; - io_write_handler[handle].this_ptr = this_ptr; - io_write_handler[handle].handler_name = name; - io_write_handler[handle].mask = mask; - } - - /* change table to reflect new handler id for that address */ - if (write_handler_id[addr] < BX_DEFAULT_IO_DEVICE) { - // another handler is already registered for that address - BX_ERROR(("IO device address conflict(write) at IO address %Xh", - (unsigned) addr)); - BX_ERROR((" conflicting devices: %s & %s", - io_write_handler[handle].handler_name, io_write_handler[write_handler_id[addr]].handler_name)); - return false; //unable to map iodevice. - } - write_handler_id[addr] = handle; - return true; // done! -} - - -// Registration of default handlers (mainly be the unmapped device) -// The trick here is to define a handler for the max index, so -// unregisterd io address will get handled by the default function -// This will be helpful when we want to unregister io handlers - - bx_bool -bx_devices_c::register_default_io_read_handler( void *this_ptr, bx_read_handler_t f, - const char *name, Bit8u mask ) -{ - unsigned handle; - - /* handle is fixed to the default I/O device */ - handle = BX_DEFAULT_IO_DEVICE; - - if (strcmp(io_read_handler[handle].handler_name, "Default")) { - BX_ERROR(("Default io read handler already registered '%s'",io_read_handler[handle].handler_name)); - return false; - } - - io_read_handler[handle].funct = f; - io_read_handler[handle].this_ptr = this_ptr; - io_read_handler[handle].handler_name = name; - io_read_handler[handle].mask = mask; - - return true; -} - - - - bx_bool -bx_devices_c::register_default_io_write_handler( void *this_ptr, bx_write_handler_t f, - const char *name, Bit8u mask ) -{ - unsigned handle; - - /* handle is fixed to the MAX */ - handle = BX_DEFAULT_IO_DEVICE; - - if (strcmp(io_write_handler[handle].handler_name, "Default")) { - BX_ERROR(("Default io write handler already registered '%s'",io_write_handler[handle].handler_name)); - return false; - } - - io_write_handler[handle].funct = f; - io_write_handler[handle].this_ptr = this_ptr; - io_write_handler[handle].handler_name = name; - io_write_handler[handle].mask = mask; - - return true; -} - - - -/* - * Read a byte of data from the IO memory address space - */ - - Bit32u BX_CPP_AttrRegparmN(2) -bx_devices_c::inp(Bit16u addr, unsigned io_len) -{ - Bit8u handle; - Bit32u ret; - - BX_INSTR_INP(addr, io_len); - - handle = read_handler_id[addr]; - if ((io_read_handler[handle].funct != NULL) && - (io_read_handler[handle].mask & io_len)) { - ret = (* io_read_handler[handle].funct)(io_read_handler[handle].this_ptr, - (Bit32u) addr, io_len); - } else { - switch (io_len) { - case 1: ret = 0xff; break; - case 2: ret = 0xffff; break; - default: ret = 0xffffffff; break; - } - BX_ERROR(("read from port 0x%04x with len %d returns 0x%x", addr, io_len, ret)); - } - BX_INSTR_INP2(addr, io_len, ret); - BX_DBG_IO_REPORT(addr, io_len, BX_READ, ret); - - return(ret); -} - - -/* - * Write a byte of data to the IO memory address space. - */ - - void BX_CPP_AttrRegparmN(3) -bx_devices_c::outp(Bit16u addr, Bit32u value, unsigned io_len) -{ - Bit8u handle; - - BX_INSTR_OUTP(addr, io_len); - BX_INSTR_OUTP2(addr, io_len, value); - - BX_DBG_IO_REPORT(addr, io_len, BX_WRITE, value); - handle = write_handler_id[addr]; - if ((io_write_handler[handle].funct != NULL) && - (io_write_handler[handle].mask & io_len)) { - (* io_write_handler[handle].funct)(io_write_handler[handle].this_ptr, - (Bit32u) addr, value, io_len); - } else { - BX_ERROR(("write to port 0x%04x with len %d ignored", addr, io_len)); - } -} - -bx_bool bx_devices_c::is_serial_enabled () -{ - for (int i=0; iget_param_bool (BXP_COMx_ENABLED(i+1))->get()) - return true; - } - return false; -} - -bx_bool bx_devices_c::is_usb_enabled () -{ - for (int i=0; iget_param_bool (BXP_USBx_ENABLED(i+1))->get()) - return true; - } - return false; -} - -bx_bool bx_devices_c::is_parallel_enabled () -{ - for (int i=0; iget_param_bool (BXP_PARPORTx_ENABLED(i+1))->get()) - return true; - } - return false; -} diff --git a/tools/ioemu/iodev/dma.cc b/tools/ioemu/iodev/dma.cc deleted file mode 100644 index afe0238a92..0000000000 --- a/tools/ioemu/iodev/dma.cc +++ /dev/null @@ -1,825 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: dma.cc,v 1.30 2003/07/31 15:29:34 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" - -#define LOG_THIS theDmaDevice-> - -#define DMA_MODE_DEMAND 0 -#define DMA_MODE_SINGLE 1 -#define DMA_MODE_BLOCK 2 -#define DMA_MODE_CASCADE 3 - -bx_dma_c *theDmaDevice = NULL; - - int -libdma_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - theDmaDevice = new bx_dma_c (); - bx_devices.pluginDmaDevice = theDmaDevice; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theDmaDevice, BX_PLUGIN_DMA); - return(0); // Success -} - - void -libdma_LTX_plugin_fini(void) -{ -} - -bx_dma_c::bx_dma_c(void) -{ - put("DMA"); - settype(DMALOG); -} - -bx_dma_c::~bx_dma_c(void) -{ - BX_DEBUG(("Exit.")); -} - - unsigned -bx_dma_c::registerDMA8Channel( - unsigned channel, - void (* dmaRead)(Bit8u *data_byte), - void (* dmaWrite)(Bit8u *data_byte), - const char *name - ) -{ - if (channel > 3) { - BX_PANIC(("registerDMA8Channel: invalid channel number(%u).", channel)); - return 0; // Fail. - } - if (BX_DMA_THIS s[0].chan[channel].used) { - BX_PANIC(("registerDMA8Channel: channel(%u) already in use.", channel)); - return 0; // Fail. - } - BX_INFO(("channel %u used by %s", channel, name)); - BX_DMA_THIS h[channel].dmaRead8 = dmaRead; - BX_DMA_THIS h[channel].dmaWrite8 = dmaWrite; - BX_DMA_THIS s[0].chan[channel].used = 1; - return 1; // OK. -} - - unsigned -bx_dma_c::registerDMA16Channel( - unsigned channel, - void (* dmaRead)(Bit16u *data_word), - void (* dmaWrite)(Bit16u *data_word), - const char *name - ) -{ - if ((channel < 4) || (channel > 7)) { - BX_PANIC(("registerDMA16Channel: invalid channel number(%u).", channel)); - return 0; // Fail. - } - if (BX_DMA_THIS s[1].chan[channel & 0x03].used) { - BX_PANIC(("registerDMA16Channel: channel(%u) already in use.", channel)); - return 0; // Fail. - } - BX_INFO(("channel %u used by %s", channel, name)); - channel &= 0x03; - BX_DMA_THIS h[channel].dmaRead16 = dmaRead; - BX_DMA_THIS h[channel].dmaWrite16 = dmaWrite; - BX_DMA_THIS s[1].chan[channel].used = 1; - return 1; // OK. -} - - unsigned -bx_dma_c::unregisterDMAChannel(unsigned channel) -{ - bx_bool ma_sl = (channel > 3); - BX_DMA_THIS s[ma_sl].chan[channel & 0x03].used = 0; - BX_INFO(("channel %u no longer used", channel)); - return 1; -} - - unsigned -bx_dma_c::get_TC(void) -{ - return BX_DMA_THIS TC; -} - - - void -bx_dma_c::init(void) -{ - unsigned c, i, j; - BX_DEBUG(("Init $Id: dma.cc,v 1.30 2003/07/31 15:29:34 vruppert Exp $")); - - /* 8237 DMA controller */ - - for (i=0; i < 2; i++) { - for (j=0; j < 4; j++) { - BX_DMA_THIS s[i].DRQ[j] = 0; - BX_DMA_THIS s[i].DACK[j] = 0; - } - } - BX_DMA_THIS HLDA = 0; - BX_DMA_THIS TC = 0; - - // 0000..000F - for (i=0x0000; i<=0x000F; i++) { - DEV_register_ioread_handler(this, read_handler, i, "DMA controller", 1); - DEV_register_iowrite_handler(this, write_handler, i, "DMA controller", 3); - } - - // 00081..008F - for (i=0x0081; i<=0x008F; i++) { - DEV_register_ioread_handler(this, read_handler, i, "DMA controller", 1); - DEV_register_iowrite_handler(this, write_handler, i, "DMA controller", 3); - } - - // 000C0..00DE - for (i=0x00C0; i<=0x00DE; i+=2) { - DEV_register_ioread_handler(this, read_handler, i, "DMA controller", 1); - DEV_register_iowrite_handler(this, write_handler, i, "DMA controller", 3); - } - - - for (i=0; i<2; i++) { - for (c=0; c<4; c++) { - BX_DMA_THIS s[i].chan[c].mode.mode_type = 0; // demand mode - BX_DMA_THIS s[i].chan[c].mode.address_decrement = 0; // address increment - BX_DMA_THIS s[i].chan[c].mode.autoinit_enable = 0; // autoinit disable - BX_DMA_THIS s[i].chan[c].mode.transfer_type = 0; // verify - BX_DMA_THIS s[i].chan[c].base_address = 0; - BX_DMA_THIS s[i].chan[c].current_address = 0; - BX_DMA_THIS s[i].chan[c].base_count = 0; - BX_DMA_THIS s[i].chan[c].current_count = 0; - BX_DMA_THIS s[i].chan[c].page_reg = 0; - BX_DMA_THIS s[i].chan[c].used = 0; - } - } - BX_DMA_THIS s[1].chan[0].used = 1; // cascade channel in use - BX_INFO(("channel 4 used by cascade")); - bios_init(); -} - -/* Remove it when guest fw ready*/ - void -bx_dma_c::bios_init(void){ - BX_DMA_THIS s[1].mask[0] = 0; // unmask cascade channel - BX_DMA_THIS s[1].chan[0].mode.mode_type = 3; // cascade mode for channel 4 -} - - void -bx_dma_c::reset(unsigned type) -{ - reset_controller(0); - reset_controller(1); - bios_init(); -} - - void -bx_dma_c::reset_controller(unsigned num) -{ - BX_DMA_THIS s[num].mask[0] = 1; - BX_DMA_THIS s[num].mask[1] = 1; - BX_DMA_THIS s[num].mask[2] = 1; - BX_DMA_THIS s[num].mask[3] = 1; - BX_DMA_THIS s[num].command_reg = 0; - BX_DMA_THIS s[num].status_reg = 0; - BX_DMA_THIS s[num].request_reg = 0; - BX_DMA_THIS s[num].temporary_reg = 0; - BX_DMA_THIS s[num].flip_flop = 0; -} - - // index to find channel from register number (only [0],[1],[2],[6] used) - Bit8u channelindex[7] = {2, 3, 1, 0, 0, 0, 0}; - - - // static IO port read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_dma_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_DMA_SMF - bx_dma_c *class_ptr = (bx_dma_c *) this_ptr; - - return( class_ptr->read(address, io_len) ); -} - - /* 8237 DMA controller */ - Bit32u BX_CPP_AttrRegparmN(2) -bx_dma_c::read( Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_DMA_SMF - - Bit8u retval; - Bit8u channel; - bx_bool ma_sl; - - BX_DEBUG(("read addr=%04x", (unsigned) address)); - -#if BX_DMA_FLOPPY_IO < 1 - /* if we're not supporting DMA/floppy IO just return a bogus value */ - return(0xff); -#endif - - switch (address) { - case 0x00: /* DMA-1 current address, channel 0 */ - case 0x02: /* DMA-1 current address, channel 1 */ - case 0x04: /* DMA-1 current address, channel 2 */ - case 0x06: /* DMA-1 current address, channel 3 */ - case 0xc0: /* DMA-2 current address, channel 0 */ - case 0xc4: /* DMA-2 current address, channel 1 */ - case 0xc8: /* DMA-2 current address, channel 2 */ - case 0xcc: /* DMA-2 current address, channel 3 */ - ma_sl = (address >= 0xc0); - channel = (address >> (1 + ma_sl)) & 0x03; - if (BX_DMA_THIS s[ma_sl].flip_flop==0) { - BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; - return(BX_DMA_THIS s[ma_sl].chan[channel].current_address & 0xff); - } - else { - BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; - return(BX_DMA_THIS s[ma_sl].chan[channel].current_address >> 8); - } - - case 0x01: /* DMA-1 current count, channel 0 */ - case 0x03: /* DMA-1 current count, channel 1 */ - case 0x05: /* DMA-1 current count, channel 2 */ - case 0x07: /* DMA-1 current count, channel 3 */ - case 0xc2: /* DMA-2 current count, channel 0 */ - case 0xc6: /* DMA-2 current count, channel 1 */ - case 0xca: /* DMA-2 current count, channel 2 */ - case 0xce: /* DMA-2 current count, channel 3 */ - ma_sl = (address >= 0xc2); - channel = (address >> (1 + ma_sl)) & 0x03; - if (BX_DMA_THIS s[ma_sl].flip_flop==0) { - BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; - return(BX_DMA_THIS s[ma_sl].chan[channel].current_count & 0xff); - } - else { - BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; - return(BX_DMA_THIS s[ma_sl].chan[channel].current_count >> 8); - } - - case 0x08: // DMA-1 Status Register - case 0xd0: // DMA-2 Status Register - // bit 7: 1 = channel 3 request - // bit 6: 1 = channel 2 request - // bit 5: 1 = channel 1 request - // bit 4: 1 = channel 0 request - // bit 3: 1 = channel 3 has reached terminal count - // bit 2: 1 = channel 2 has reached terminal count - // bit 1: 1 = channel 1 has reached terminal count - // bit 0: 1 = channel 0 has reached terminal count - // reading this register clears lower 4 bits (hold flags) - ma_sl = (address == 0xd0); - retval = BX_DMA_THIS s[ma_sl].status_reg; - BX_DMA_THIS s[ma_sl].status_reg &= 0xf0; - return(retval); - break; - case 0x0d: // DMA-1: temporary register - case 0xda: // DMA-2: temporary register - ma_sl = (address == 0xda); - BX_ERROR(("DMA-%d: read of temporary register", ma_sl+1)); - // Note: write to 0x0D clears temporary register - return(0); - break; - - case 0x0081: // DMA-1 page register, channel 2 - case 0x0082: // DMA-1 page register, channel 3 - case 0x0083: // DMA-1 page register, channel 1 - case 0x0087: // DMA-1 page register, channel 0 - channel = channelindex[address - 0x81]; - return( BX_DMA_THIS s[0].chan[channel].page_reg ); - - case 0x0089: // DMA-2 page register, channel 2 - case 0x008a: // DMA-2 page register, channel 3 - case 0x008b: // DMA-2 page register, channel 1 - case 0x008f: // DMA-2 page register, channel 0 - channel = channelindex[address - 0x89]; - return( BX_DMA_THIS s[1].chan[channel].page_reg ); - - case 0x0084: - case 0x0085: - case 0x0086: - case 0x0088: - case 0x008c: - case 0x008d: - case 0x008e: - BX_DEBUG(("read: extra page register 0x%04x unsupported", (unsigned) address)); - return(0); - - default: - BX_ERROR(("read: unsupported address=%04x", (unsigned) address)); - return(0); - } -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_dma_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_DMA_SMF - bx_dma_c *class_ptr = (bx_dma_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - - - /* 8237 DMA controller */ - void BX_CPP_AttrRegparmN(3) -bx_dma_c::write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_DMA_SMF - Bit8u set_mask_bit; - Bit8u channel; - bx_bool ma_sl; - - if (io_len > 1) { - if ( (io_len == 2) && (address == 0x0b) ) { -#if BX_USE_DMA_SMF - BX_DMA_THIS write_handler(NULL, address, value & 0xff, 1); - BX_DMA_THIS write_handler(NULL, address+1, value >> 8, 1); -#else - BX_DMA_THIS write(address, value & 0xff, 1); - BX_DMA_THIS write(address+1, value >> 8, 1); -#endif - return; - } - - BX_ERROR(("io write to address %08x, len=%u", - (unsigned) address, (unsigned) io_len)); - return; - } - - BX_DEBUG(("write: address=%04x value=%02x", - (unsigned) address, (unsigned) value)); - -#if BX_DMA_FLOPPY_IO < 1 - /* if we're not supporting DMA/floppy IO just return */ - return; -#endif - - switch (address) { - case 0x00: - case 0x02: - case 0x04: - case 0x06: - case 0xc0: - case 0xc4: - case 0xc8: - case 0xcc: - ma_sl = (address >= 0xc0); - channel = (address >> (1 + ma_sl)) & 0x03; - BX_DEBUG((" DMA-%d base and current address, channel %d", ma_sl+1, channel)); - if (BX_DMA_THIS s[ma_sl].flip_flop==0) { /* 1st byte */ - BX_DMA_THIS s[ma_sl].chan[channel].base_address = value; - BX_DMA_THIS s[ma_sl].chan[channel].current_address = value; - } - else { /* 2nd byte */ - BX_DMA_THIS s[ma_sl].chan[channel].base_address |= (value << 8); - BX_DMA_THIS s[ma_sl].chan[channel].current_address |= (value << 8); - BX_DEBUG((" base = %04x", - (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].base_address)); - BX_DEBUG((" curr = %04x", - (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].current_address)); - } - BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; - return; - break; - - case 0x01: - case 0x03: - case 0x05: - case 0x07: - case 0xc2: - case 0xc6: - case 0xca: - case 0xce: - ma_sl = (address >= 0xc2); - channel = (address >> (1 + ma_sl)) & 0x03; - BX_DEBUG((" DMA-%d base and current count, channel %d", ma_sl+1, channel)); - if (BX_DMA_THIS s[ma_sl].flip_flop==0) { /* 1st byte */ - BX_DMA_THIS s[ma_sl].chan[channel].base_count = value; - BX_DMA_THIS s[ma_sl].chan[channel].current_count = value; - } - else { /* 2nd byte */ - BX_DMA_THIS s[ma_sl].chan[channel].base_count |= (value << 8); - BX_DMA_THIS s[ma_sl].chan[channel].current_count |= (value << 8); - BX_DEBUG((" base = %04x", - (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].base_count)); - BX_DEBUG((" curr = %04x", - (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].current_count)); - } - BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; - return; - break; - - case 0x08: /* DMA-1: command register */ - case 0xd0: /* DMA-2: command register */ - ma_sl = (address == 0xd0); - if (value != 0x00) - BX_ERROR(("write to command register: value(%02xh) not 0x00", - (unsigned) value)); - BX_DMA_THIS s[ma_sl].command_reg = value; - return; - break; - - case 0x09: // DMA-1: request register - case 0xd2: // DMA-2: request register - ma_sl = (address == 0xd2); - channel = value & 0x03; - BX_ERROR(("DMA-%d: write to request register (%02x)", ma_sl+1, (unsigned) value)); - // note: write to 0x0d clears this register - if (value & 0x04) { - // set request bit - BX_DMA_THIS s[ma_sl].status_reg |= (1 << (channel+4)); - BX_DEBUG(("DMA-%d: set request bit for channel %u", ma_sl+1, (unsigned) channel)); - } - else { - // clear request bit - BX_DMA_THIS s[ma_sl].status_reg &= ~(1 << (channel+4)); - BX_DEBUG(("DMA-%d: cleared request bit for channel %u", ma_sl+1, (unsigned) channel)); - } - control_HRQ(ma_sl); - return; - break; - - case 0x0a: - case 0xd4: - ma_sl = (address == 0xd4); - set_mask_bit = value & 0x04; - channel = value & 0x03; - BX_DMA_THIS s[ma_sl].mask[channel] = (set_mask_bit > 0); - BX_DEBUG(("DMA-%d: set_mask_bit=%u, channel=%u, mask now=%02xh", ma_sl+1, - (unsigned) set_mask_bit, (unsigned) channel, (unsigned) BX_DMA_THIS s[ma_sl].mask[channel])); - control_HRQ(ma_sl); - return; - break; - - case 0x0b: /* DMA-1 mode register */ - case 0xd6: /* DMA-2 mode register */ - ma_sl = (address == 0xd6); - channel = value & 0x03; - BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type = (value >> 6) & 0x03; - BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement = (value >> 5) & 0x01; - BX_DMA_THIS s[ma_sl].chan[channel].mode.autoinit_enable = (value >> 4) & 0x01; - BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type = (value >> 2) & 0x03; - BX_DEBUG(("DMA-%d: mode register[%u] = %02x", ma_sl+1, - (unsigned) channel, (unsigned) value)); - return; - break; - - case 0x0c: /* DMA-1 clear byte flip/flop */ - case 0xd8: /* DMA-2 clear byte flip/flop */ - ma_sl = (address == 0xd8); - BX_DEBUG(("DMA-%d: clear flip/flop", ma_sl+1)); - BX_DMA_THIS s[ma_sl].flip_flop = 0; - return; - break; - - case 0x0d: // DMA-1: master clear - case 0xda: // DMA-2: master clear - ma_sl = (address == 0xda); - BX_DEBUG(("DMA-%d: master clear", ma_sl+1)); - // writing any value to this port resets DMA controller 1 / 2 - // same action as a hardware reset - // mask register is set (chan 0..3 disabled) - // command, status, request, temporary, and byte flip-flop are all cleared - reset_controller(ma_sl); - return; - break; - - case 0x0e: // DMA-1: clear mask register - case 0xdc: // DMA-2: clear mask register - ma_sl = (address == 0xdc); - BX_DEBUG(("DMA-%d: clear mask register", ma_sl+1)); - BX_DMA_THIS s[ma_sl].mask[0] = 0; - BX_DMA_THIS s[ma_sl].mask[1] = 0; - BX_DMA_THIS s[ma_sl].mask[2] = 0; - BX_DMA_THIS s[ma_sl].mask[3] = 0; - control_HRQ(ma_sl); - return; - break; - - case 0x0f: // DMA-1: write all mask bits - case 0xde: // DMA-2: write all mask bits - ma_sl = (address == 0xde); - BX_DEBUG(("DMA-%d: write all mask bits", ma_sl+1)); - BX_DMA_THIS s[ma_sl].mask[0] = value & 0x01; value >>= 1; - BX_DMA_THIS s[ma_sl].mask[1] = value & 0x01; value >>= 1; - BX_DMA_THIS s[ma_sl].mask[2] = value & 0x01; value >>= 1; - BX_DMA_THIS s[ma_sl].mask[3] = value & 0x01; - control_HRQ(ma_sl); - return; - break; - - case 0x81: /* DMA-1 page register, channel 2 */ - case 0x82: /* DMA-1 page register, channel 3 */ - case 0x83: /* DMA-1 page register, channel 1 */ - case 0x87: /* DMA-1 page register, channel 0 */ - /* address bits A16-A23 for DMA channel */ - channel = channelindex[address - 0x81]; - BX_DMA_THIS s[0].chan[channel].page_reg = value; - BX_DEBUG(("DMA-1: page register %d = %02x", channel, (unsigned) value)); - return; - break; - - case 0x89: /* DMA-2 page register, channel 2 */ - case 0x8a: /* DMA-2 page register, channel 3 */ - case 0x8b: /* DMA-2 page register, channel 1 */ - case 0x8f: /* DMA-2 page register, channel 0 */ - /* address bits A16-A23 for DMA channel */ - channel = channelindex[address - 0x89]; - BX_DMA_THIS s[1].chan[channel].page_reg = value; - BX_DEBUG(("DMA-2: page register %d = %02x", channel + 4, (unsigned) value)); - return; - break; - - case 0x0084: - case 0x0085: - case 0x0086: - case 0x0088: - case 0x008c: - case 0x008d: - case 0x008e: - BX_DEBUG(("write: extra page register 0x%04x unsupported", (unsigned) address)); - return; - break; - - default: - BX_ERROR(("write ignored: %04xh = %02xh", - (unsigned) address, (unsigned) value)); - } -} - - void -bx_dma_c::set_DRQ(unsigned channel, bx_bool val) -{ - Bit32u dma_base, dma_roof; - bx_bool ma_sl; - - if (channel > 7) { - BX_PANIC(("set_DRQ() channel > 7")); - return; - } - ma_sl = (channel > 3); - BX_DMA_THIS s[ma_sl].DRQ[channel & 0x03] = val; - if (!BX_DMA_THIS s[ma_sl].chan[channel & 0x03].used) { - BX_PANIC(("set_DRQ(): channel %d not connected to device", channel)); - return; - } - channel &= 0x03; - if (!val) { - //BX_DEBUG(("bx_dma_c::DRQ(): val == 0")); - // clear bit in status reg - BX_DMA_THIS s[ma_sl].status_reg &= ~(1 << (channel+4)); - - control_HRQ(ma_sl); - return; - } - -#if 0 - BX_INFO(("mask[%d]: %02x", channel, (unsigned) BX_DMA_THIS s[0].mask[channel])); - BX_INFO(("flip_flop: %u", (unsigned) BX_DMA_THIS s[0].flip_flop)); - BX_INFO(("status_reg: %02x", (unsigned) BX_DMA_THIS s[0].status_reg)); - BX_INFO(("mode_type: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.mode_type)); - BX_INFO(("address_decrement: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.address_decrement)); - BX_INFO(("autoinit_enable: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.autoinit_enable)); - BX_INFO(("transfer_type: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.transfer_type)); - BX_INFO(("base_address: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].base_address)); - BX_INFO(("current_address: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].current_address)); - BX_INFO(("base_count: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].base_count)); - BX_INFO(("current_count: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].current_count)); - BX_INFO(("page_reg: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].page_reg)); -#endif - - BX_DMA_THIS s[ma_sl].status_reg |= (1 << (channel+4)); - - if ( (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_SINGLE) && - (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_DEMAND) && - (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_CASCADE) ) - BX_PANIC(("set_DRQ: mode_type(%02x) not handled", - (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type)); - - dma_base = (BX_DMA_THIS s[ma_sl].chan[channel].page_reg << 16) | - (BX_DMA_THIS s[ma_sl].chan[channel].base_address << ma_sl); - if (BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement==0) { - dma_roof = dma_base + (BX_DMA_THIS s[ma_sl].chan[channel].base_count << ma_sl); - } else { - dma_roof = dma_base - (BX_DMA_THIS s[ma_sl].chan[channel].base_count << ma_sl); - } - if ( (dma_base & (0x7fff0000 << ma_sl)) != (dma_roof & (0x7fff0000 << ma_sl)) ) { - BX_INFO(("dma_base = %08x", (unsigned) dma_base)); - BX_INFO(("dma_base_count = %08x", (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].base_count)); - BX_INFO(("dma_roof = %08x", (unsigned) dma_roof)); - BX_PANIC(("request outside %dk boundary", 64 << ma_sl)); - } - - control_HRQ(ma_sl); -} - - void -bx_dma_c::control_HRQ(bx_bool ma_sl) -{ - unsigned channel; - - // deassert HRQ if no DRQ is pending - if ((BX_DMA_THIS s[ma_sl].status_reg & 0xf0) == 0) { - if (ma_sl) { - bx_pc_system.set_HRQ(0); - } else { - BX_DMA_THIS set_DRQ(4, 0); - } - return; - } - // find highest priority channel - for (channel=0; channel<4; channel++) { - if ( (BX_DMA_THIS s[ma_sl].status_reg & (1 << (channel+4))) && - (BX_DMA_THIS s[ma_sl].mask[channel]==0) ) { - if (ma_sl) { - // assert Hold ReQuest line to CPU - bx_pc_system.set_HRQ(1); - } else { - // send DRQ to cascade channel of the master - BX_DMA_THIS set_DRQ(4, 1); - } - break; - } - } -} - - void -bx_dma_c::raise_HLDA(void) -{ - unsigned channel; - Bit32u phy_addr; - bx_bool count_expired = 0; - bx_bool ma_sl = 0; - - BX_DMA_THIS HLDA = 1; - // find highest priority channel - for (channel=0; channel<4; channel++) { - if ( (BX_DMA_THIS s[1].status_reg & (1 << (channel+4))) && - (BX_DMA_THIS s[1].mask[channel]==0) ) { - ma_sl = 1; - break; - } - } - if (channel == 0) { // master cascade channel - BX_DMA_THIS s[1].DACK[0] = 1; - for (channel=0; channel<4; channel++) { - if ( (BX_DMA_THIS s[0].status_reg & (1 << (channel+4))) && - (BX_DMA_THIS s[0].mask[channel]==0) ) { - ma_sl = 0; - break; - } - } - } - if (channel >= 4) { - // wait till they're unmasked - return; - } - - //BX_DEBUG(("hlda: OK in response to DRQ(%u)", (unsigned) channel)); - phy_addr = (BX_DMA_THIS s[ma_sl].chan[channel].page_reg << 16) | - (BX_DMA_THIS s[ma_sl].chan[channel].current_address << ma_sl); - - BX_DMA_THIS s[ma_sl].DACK[channel] = 1; - // check for expiration of count, so we can signal TC and DACK(n) - // at the same time. - if (BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement==0) - BX_DMA_THIS s[ma_sl].chan[channel].current_address++; - else - BX_DMA_THIS s[ma_sl].chan[channel].current_address--; - BX_DMA_THIS s[ma_sl].chan[channel].current_count--; - if (BX_DMA_THIS s[ma_sl].chan[channel].current_count == 0xffff) { - // count expired, done with transfer - // assert TC, deassert HRQ & DACK(n) lines - BX_DMA_THIS s[ma_sl].status_reg |= (1 << channel); // hold TC in status reg - BX_DMA_THIS TC = 1; - count_expired = 1; - if (BX_DMA_THIS s[ma_sl].chan[channel].mode.autoinit_enable == 0) { - // set mask bit if not in autoinit mode - BX_DMA_THIS s[ma_sl].mask[channel] = 1; - } - else { - // count expired, but in autoinit mode - // reload count and base address - BX_DMA_THIS s[ma_sl].chan[channel].current_address = - BX_DMA_THIS s[ma_sl].chan[channel].base_address; - BX_DMA_THIS s[ma_sl].chan[channel].current_count = - BX_DMA_THIS s[ma_sl].chan[channel].base_count; - } - } - - Bit8u data_byte; - Bit16u data_word; - - if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 1) { // write - // DMA controlled xfer of byte from I/O to Memory - - if (!ma_sl) { - if (BX_DMA_THIS h[channel].dmaWrite8) - BX_DMA_THIS h[channel].dmaWrite8(&data_byte); - else - BX_PANIC(("no dmaWrite handler for channel %u.", channel)); - - BX_MEM_WRITE_PHYSICAL(phy_addr, 1, &data_byte); - - BX_DBG_DMA_REPORT(phy_addr, 1, BX_WRITE, data_byte); - } - else { - if (BX_DMA_THIS h[channel].dmaWrite16) - BX_DMA_THIS h[channel].dmaWrite16(&data_word); - else - BX_PANIC(("no dmaWrite handler for channel %u.", channel)); - - BX_MEM_WRITE_PHYSICAL(phy_addr, 2, &data_word); - - BX_DBG_DMA_REPORT(phy_addr, 2, BX_WRITE, data_word); - } - } - else if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 2) { // read - // DMA controlled xfer of byte from Memory to I/O - - if (!ma_sl) { - BX_MEM_READ_PHYSICAL(phy_addr, 1, &data_byte); - - if (BX_DMA_THIS h[channel].dmaRead8) - BX_DMA_THIS h[channel].dmaRead8(&data_byte); - - BX_DBG_DMA_REPORT(phy_addr, 1, BX_READ, data_byte); - } - else { - BX_MEM_READ_PHYSICAL(phy_addr, 2, &data_word); - - if (BX_DMA_THIS h[channel].dmaRead16) - BX_DMA_THIS h[channel].dmaRead16(&data_word); - - BX_DBG_DMA_REPORT(phy_addr, 2, BX_READ, data_word); - } - } - else if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 0) { - // verify - - if (!ma_sl) { - if (BX_DMA_THIS h[channel].dmaWrite8) - BX_DMA_THIS h[channel].dmaWrite8(&data_byte); - else - BX_PANIC(("no dmaWrite handler for channel %u.", channel)); - } - else { - if (BX_DMA_THIS h[channel].dmaWrite16) - BX_DMA_THIS h[channel].dmaWrite16(&data_word); - else - BX_PANIC(("no dmaWrite handler for channel %u.", channel)); - } - } - else { - BX_PANIC(("hlda: transfer_type 3 is undefined")); - } - - if (count_expired) { - BX_DMA_THIS TC = 0; // clear TC, adapter card already notified - BX_DMA_THIS HLDA = 0; - bx_pc_system.set_HRQ(0); // clear HRQ to CPU - BX_DMA_THIS s[ma_sl].DACK[channel] = 0; // clear DACK to adapter card - if (!ma_sl) { - BX_DMA_THIS set_DRQ(4, 0); // clear DRQ to cascade - BX_DMA_THIS s[1].DACK[0] = 0; // clear DACK to cascade - } - } -} diff --git a/tools/ioemu/iodev/dma.h b/tools/ioemu/iodev/dma.h deleted file mode 100644 index 9f6c4eb60e..0000000000 --- a/tools/ioemu/iodev/dma.h +++ /dev/null @@ -1,114 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: dma.h,v 1.15 2003/05/03 07:41:27 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -#ifndef _PCDMA_H -#define _PCDMA_H - - -#if BX_USE_DMA_SMF -# define BX_DMA_SMF static -# define BX_DMA_THIS theDmaDevice-> -#else -# define BX_DMA_SMF -# define BX_DMA_THIS this-> -#endif - - - -class bx_dma_c : public bx_dma_stub_c { -public: - - bx_dma_c(); - ~bx_dma_c(void); - - virtual void init(void); - virtual void bios_init(void); - virtual void reset(unsigned type); - virtual void raise_HLDA(void); - virtual void set_DRQ(unsigned channel, bx_bool val); - virtual unsigned get_TC(void); - - virtual unsigned registerDMA8Channel(unsigned channel, - void (* dmaRead)(Bit8u *data_byte), - void (* dmaWrite)(Bit8u *data_byte), - const char *name); - virtual unsigned registerDMA16Channel(unsigned channel, - void (* dmaRead)(Bit16u *data_word), - void (* dmaWrite)(Bit16u *data_word), - const char *name); - virtual unsigned unregisterDMAChannel(unsigned channel); - -private: - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); -#if !BX_USE_DMA_SMF - Bit32u read( Bit32u address, unsigned io_len) BX_CPP_AttrRegparmN(2); - void write(Bit32u address, Bit32u value, unsigned io_len) BX_CPP_AttrRegparmN(3); -#endif - BX_DMA_SMF void control_HRQ(bx_bool ma_sl); - BX_DMA_SMF void reset_controller(unsigned num); - - struct { - bx_bool DRQ[4]; // DMA Request - bx_bool DACK[4]; // DMA Acknowlege - - bx_bool mask[4]; - bx_bool flip_flop; - Bit8u status_reg; - Bit8u command_reg; - Bit8u request_reg; - Bit8u temporary_reg; - struct { - struct { - Bit8u mode_type; - Bit8u address_decrement; - Bit8u autoinit_enable; - Bit8u transfer_type; - } mode; - Bit16u base_address; - Bit16u current_address; - Bit16u base_count; - Bit16u current_count; - Bit8u page_reg; - bx_bool used; - } chan[4]; /* DMA channels 0..3 */ - } s[2]; // state information DMA-1 / DMA-2 - - bx_bool HLDA; // Hold Acknowlege - bx_bool TC; // Terminal Count - - struct { - void (* dmaRead8)(Bit8u *data_byte); - void (* dmaWrite8)(Bit8u *data_byte); - void (* dmaRead16)(Bit16u *data_word); - void (* dmaWrite16)(Bit16u *data_word); - } h[4]; // DMA read and write handlers - - }; - -#endif // #ifndef _PCDMA_H diff --git a/tools/ioemu/iodev/eth.cc b/tools/ioemu/iodev/eth.cc deleted file mode 100644 index d6ee9d2948..0000000000 --- a/tools/ioemu/iodev/eth.cc +++ /dev/null @@ -1,194 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: eth.cc,v 1.16 2003/04/28 13:01:09 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// eth.cc - helper code to find and create pktmover classes - -// Peter Grehan (grehan@iprg.nokia.com) coded all of this -// NE2000/ether stuff. - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_NE2K_SUPPORT - -#define LOG_THIS /* not needed */ - -eth_locator_c *eth_locator_c::all; - -// -// Each pktmover module has a static locator class that registers -// here -// -eth_locator_c::eth_locator_c(const char *type) -{ - next = all; - all = this; - this->type = type; -} - -#ifdef ETH_NULL -extern class bx_null_locator_c bx_null_match; -#endif -#ifdef ETH_FBSD -extern class bx_fbsd_locator_c bx_fbsd_match; -#endif -#ifdef ETH_LINUX -extern class bx_linux_locator_c bx_linux_match; -#endif -#ifdef ETH_WIN32 -extern class bx_win32_locator_c bx_win32_match; -#endif -#if HAVE_ETHERTAP -extern class bx_tap_locator_c bx_tap_match; -#endif -#if HAVE_TUNTAP -extern class bx_tuntap_locator_c bx_tuntap_match; -#endif -#ifdef ETH_TEST -extern bx_test_match; -#endif -#ifdef ETH_ARPBACK -extern class bx_arpback_locator_c bx_arpback_match; -#endif - -// -// Called by ethernet chip emulations to locate and create a pktmover -// object -// -eth_pktmover_c * -eth_locator_c::create(const char *type, const char *netif, - const char *macaddr, - eth_rx_handler_t rxh, void *rxarg) -{ -#ifdef eth_static_constructors - for (eth_locator_c *p = all; p != NULL; p = p->next) { - if (strcmp(type, p->type) == 0) - return (p->allocate(netif, macaddr, rxh, rxarg)); - } -#else - eth_locator_c *ptr = 0; - -#ifdef ETH_ARPBACK - { - if (!strcmp(type, "arpback")) - ptr = (eth_locator_c *) &bx_arpback_match; - } -#endif -#ifdef ETH_NULL - { - if (!strcmp(type, "null")) - ptr = (eth_locator_c *) &bx_null_match; - } -#endif -#ifdef ETH_FBSD - { - if (!strcmp(type, "fbsd")) - ptr = (eth_locator_c *) &bx_fbsd_match; - } -#endif -#ifdef ETH_LINUX - { - if (!strcmp(type, "linux")) - ptr = (eth_locator_c *) &bx_linux_match; - } -#endif -#if HAVE_TUNTAP - { - if (!strcmp(type, "tuntap")) - ptr = (eth_locator_c *) &bx_tuntap_match; - } -#endif -#if HAVE_ETHERTAP - { - if (!strcmp(type, "tap")) - ptr = (eth_locator_c *) &bx_tap_match; - } -#endif -#ifdef ETH_WIN32 - { - if(!strcmp(type, "win32")) - ptr = (eth_locator_c *) &bx_win32_match; - } -#endif -#ifdef ETH_TEST - { - if (!strcmp(type, "test")) - ptr = (eth_locator_c *) &bx_test_match; - } -#endif - if (ptr) - return (ptr->allocate(netif, macaddr, rxh, rxarg)); -#endif - - return (NULL); -} - -#if (HAVE_ETHERTAP==1) || (HAVE_TUNTAP==1) - -extern "C" { -#include -}; - -#undef LOG_THIS -#define LOG_THIS bx_devices.pluginNE2kDevice-> - -// This is a utility script used for tuntap or ethertap -int execute_script( char* scriptname, char* arg1 ) -{ - int pid,status; - - if (!(pid=fork())) { - char filename[BX_PATHNAME_LEN]; - if ( scriptname[0]=='/' ) { - strcpy (filename, scriptname); - } - else { - getcwd (filename, BX_PATHNAME_LEN); - strcat (filename, "/"); - strcat (filename, scriptname); - } - - // execute the script - BX_INFO(("Executing script '%s %s'",filename,arg1)); - execle(filename, scriptname, arg1, NULL, NULL); - - // if we get here there has been a problem - exit(-1); - } - - wait (&status); - if (!WIFEXITED(status)) { - return -1; - } - return WEXITSTATUS(status); -} - -#endif // (HAVE_ETHERTAP==1) || (HAVE_TUNTAP==1) - -#endif /* if BX_NE2K_SUPPORT */ diff --git a/tools/ioemu/iodev/eth.h b/tools/ioemu/iodev/eth.h deleted file mode 100644 index 8ac8c6ff3e..0000000000 --- a/tools/ioemu/iodev/eth.h +++ /dev/null @@ -1,76 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: eth.h,v 1.12 2003/04/26 14:48:45 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// Peter Grehan (grehan@iprg.nokia.com) coded all of this -// NE2000/ether stuff. - -// eth.h - see eth_null.cc for implementation details - -typedef void (*eth_rx_handler_t)(void *arg, const void *buf, unsigned len); - -int execute_script(char *name, char* arg1); - -// -// The eth_pktmover class is used by ethernet chip emulations -// to interface to the outside world. An instance of this -// would allow frames to be sent to and received from some -// entity. An example would be the packet filter on a Unix -// system, an NDIS driver in promisc mode on WinNT, or maybe -// a simulated network that talks to another process. -// -class eth_pktmover_c { -public: - virtual void sendpkt(void *buf, unsigned io_len) = 0; - virtual ~eth_pktmover_c (void) {} -protected: - eth_rx_handler_t rxh; // receive callback - void *rxarg; -}; - - -// -// The eth_locator class is used by pktmover classes to register -// their name. Chip emulations use the static 'create' method -// to locate and instantiate a pktmover class. -// -class eth_locator_c { -public: - static eth_pktmover_c *create(const char *type, const char *netif, - const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg); -protected: - eth_locator_c(const char *type); - virtual eth_pktmover_c *allocate(const char *netif, - const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg) = 0; -private: - static eth_locator_c *all; - eth_locator_c *next; - const char *type; -}; - diff --git a/tools/ioemu/iodev/eth_arpback.cc b/tools/ioemu/iodev/eth_arpback.cc deleted file mode 100644 index 0f30711dfb..0000000000 --- a/tools/ioemu/iodev/eth_arpback.cc +++ /dev/null @@ -1,214 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: eth_arpback.cc,v 1.11 2002/11/20 19:06:22 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// eth_arpback.cc - basic ethernet packetmover, only responds to ARP - -// Various networking docs: -// http://www.graphcomp.com/info/rfc/ -// rfc0826: arp -// rfc0903: rarp - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" - -#if BX_NE2K_SUPPORT && defined(ETH_ARPBACK) - -#include "crc32.h" -#include "eth_packetmaker.h" -#define LOG_THIS bx_devices.pluginNE2kDevice-> - - -//static const Bit8u external_mac[]={0xB0, 0xC4, 0x20, 0x20, 0x00, 0x00, 0x00}; -//static const Bit8u internal_mac[]={0xB0, 0xC4, 0x20, 0x00, 0x00, 0x00, 0x00}; -//static const Bit8u external_ip[]={ 192, 168, 0, 2, 0x00 }; -//static const Bit8u broadcast_mac[]={0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00}; -//static const Bit8u ethtype_arp[]={0x08, 0x06, 0x00}; - -#define MAX_FRAME_SIZE 2048 - -// -// Define the class. This is private to this module -// -class bx_arpback_pktmover_c : public eth_pktmover_c { -public: - bx_arpback_pktmover_c(const char *netif, const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg); - void sendpkt(void *buf, unsigned io_len); -private: - int rx_timer_index; - static void rx_timer_handler(void *); - void rx_timer(void); - FILE *txlog, *txlog_txt; - //Bit8u arpbuf[MAX_FRAME_SIZE]; - //Bit32u buflen; - //bx_bool bufvalid; - //CRC_Generator mycrc; - eth_ETHmaker packetmaker; -}; - - -// -// Define the static class that registers the derived pktmover class, -// and allocates one on request. -// -class bx_arpback_locator_c : public eth_locator_c { -public: - bx_arpback_locator_c(void) : eth_locator_c("arpback") {} -protected: - eth_pktmover_c *allocate(const char *netif, const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg) { - return (new bx_arpback_pktmover_c(netif, macaddr, rxh, rxarg)); - } -} bx_arpback_match; - - -// -// Define the methods for the bx_arpback_pktmover derived class -// - -// the constructor -bx_arpback_pktmover_c::bx_arpback_pktmover_c(const char *netif, - const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg) -{ - this->rx_timer_index = - bx_pc_system.register_timer(this, this->rx_timer_handler, 1000, - 1, 1, "eth_arpback"); // continuous, active - this->rxh = rxh; - this->rxarg = rxarg; - //bufvalid=0; - packetmaker.init(); -#if BX_ETH_NULL_LOGGING - // Start the rx poll - // eventually Bryce wants txlog to dump in pcap format so that - // tcpdump -r FILE can read it and interpret packets. - txlog = fopen ("ne2k-tx.log", "wb"); - if (!txlog) BX_PANIC (("open ne2k-tx.log failed")); - txlog_txt = fopen ("ne2k-txdump.txt", "wb"); - if (!txlog_txt) BX_PANIC (("open ne2k-txdump.txt failed")); - fprintf (txlog_txt, "arpback packetmover readable log file\n"); - fprintf (txlog_txt, "net IF = %s\n", netif); - fprintf (txlog_txt, "MAC address = "); - for (int i=0; i<6; i++) - fprintf (txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : ""); - fprintf (txlog_txt, "\n--\n"); - fflush (txlog_txt); -#endif -} - -void -bx_arpback_pktmover_c::sendpkt(void *buf, unsigned io_len) -{ - if(io_len0) - fprintf (txlog_txt, "\n"); - fprintf (txlog_txt, "%02x ", charbuf[n]); - } - fprintf (txlog_txt, "\n--\n"); - // flush log so that we see the packets as they arrive w/o buffering - fflush (txlog); - fflush (txlog_txt); -#endif -} - -void bx_arpback_pktmover_c::rx_timer_handler (void * this_ptr) -{ -#if BX_ETH_NULL_LOGGING - BX_DEBUG (("rx_timer_handler")); -#endif - bx_arpback_pktmover_c *class_ptr = ((bx_arpback_pktmover_c *)this_ptr); - - class_ptr->rx_timer(); -} - -void bx_arpback_pktmover_c::rx_timer (void) -{ - int nbytes = 0; - struct bpf_hdr *bhdr; - eth_packet rubble; - - if(packetmaker.getpacket(rubble)) { - //bufvalid=0; - void * buf=rubble.buf; - unsigned io_len=rubble.len; - Bit32u n; - fprintf (txlog_txt, "NE2K receiving a packet, length %u\n", io_len); - Bit8u *charbuf = (Bit8u *)buf; - for (n=0; n0) - fprintf (txlog_txt, "\n"); - fprintf (txlog_txt, "%02x ", charbuf[n]); - } - fprintf (txlog_txt, "\n--\n"); - fflush (txlog_txt); - - (*rxh)(rxarg, buf, io_len); - } -} - -#endif /* if BX_NE2K_SUPPORT && defined(ETH_ARPBACK) */ - diff --git a/tools/ioemu/iodev/eth_fbsd.cc b/tools/ioemu/iodev/eth_fbsd.cc deleted file mode 100644 index 0c24b9b828..0000000000 --- a/tools/ioemu/iodev/eth_fbsd.cc +++ /dev/null @@ -1,385 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: eth_fbsd.cc,v 1.26 2002/11/20 19:06:22 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// Peter Grehan (grehan@iprg.nokia.com) coded all of this -// NE2000/ether stuff. - -// eth_fbsd.cc - A FreeBSD packet filter implementation of -// an ethernet pktmover. There are some problems and limitations -// with FreeBSD: -// - the source address of the frame is overwritten by -// the hosts's source address. This causes problems with -// learning bridges - since they cannot determine where -// BOCHS 'is', they broadcast the frame to all ports. -// - packets cannot be sent from BOCHS to the host -// - TCP performance seems to be abysmal; I think this is -// a timing problem somewhere. -// - I haven't handled the case where multiple frames arrive -// in a single BPF read. -// -// The /dev/bpf* devices need to be set up with the appropriate -// permissions for this to work. -// -// The config line in .bochsrc should look something like: -// -// ne2k: ioaddr=0x280, irq=9, mac=00:a:b:c:1:2, ethmod=fbsd, ethdev=fxp0 -// - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_NE2K_SUPPORT && defined(ETH_FBSD) - -#define LOG_THIS bx_devices.pluginNE2kDevice-> - -extern "C" { -#include -#include -#include -#include -#include -#include -}; - -#define BX_BPF_POLL 1000 // Poll for a frame every 250 usecs - -#define BX_BPF_BUFSIZ 2048 // enough for an ether frame + bpf hdr - -#define BX_BPF_INSNSIZ 8 // number of bpf insns - -// template filter for a unicast mac address and all -// multicast/broadcast frames -static const struct bpf_insn macfilter[] = { - BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2), // A <- P[2:4] - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0xaaaaaaaa, 0, 2), // if A != 0xaaaaaaa GOTO LABEL-1 - BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 0), // A <- P[0:2] - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0000aaaa, 2, 0), // if A == 0xaaaa GOTO ACCEPT - // LABEL-1 - BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 0), // A <- P[0:1] - BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x01, 0, 1), // if !(A & 1) GOTO LABEL-REJECT - // LABEL-ACCEPT - BPF_STMT(BPF_RET, 1514), // Accept packet - // LABEL-REJECT - BPF_STMT(BPF_RET, 0), // Reject packet -}; - -// template filter for all frames -static const struct bpf_insn promiscfilter[] = { - BPF_STMT(BPF_RET, 1514) -}; - -// -// Define the class. This is private to this module -// -class bx_fbsd_pktmover_c : public eth_pktmover_c { -public: - bx_fbsd_pktmover_c(const char *netif, - const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg); - void sendpkt(void *buf, unsigned io_len); - -private: - char *fbsd_macaddr[6]; - int bpf_fd; - static void rx_timer_handler(void *); - void rx_timer(void); - int rx_timer_index; - struct bpf_insn filter[BX_BPF_INSNSIZ]; - FILE *ne2klog, *ne2klog_txt; -}; - - -// -// Define the static class that registers the derived pktmover class, -// and allocates one on request. -// -class bx_fbsd_locator_c : public eth_locator_c { -public: - bx_fbsd_locator_c(void) : eth_locator_c("fbsd") {} -protected: - eth_pktmover_c *allocate(const char *netif, - const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg) { - return (new bx_fbsd_pktmover_c(netif, macaddr, rxh, rxarg)); - } -} bx_fbsd_match; - - -// -// Define the methods for the bx_fbsd_pktmover derived class -// - -// the constructor -// -// Open a bpf file descriptor, and attempt to bind to -// the specified netif (Replicates libpcap open code) -// -bx_fbsd_pktmover_c::bx_fbsd_pktmover_c(const char *netif, - const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg) -{ - char device[sizeof "/dev/bpf000"]; - int tmpfd; - int n = 0; - struct ifreq ifr; - struct bpf_version bv; - struct bpf_program bp; - u_int v; - - memcpy(fbsd_macaddr, macaddr, 6); - - do { - (void)sprintf(device, "/dev/bpf%d", n++); - this->bpf_fd = open(device, O_RDWR); - BX_DEBUG(("tried %s, returned %d (%s)",device,this->bpf_fd,strerror(errno))); - if(errno == EACCES) - break; - } while (this->bpf_fd == -1); - - if (this->bpf_fd == -1) { - BX_PANIC(("eth_freebsd: could not open packet filter: %s", strerror(errno))); - return; - } - - if (ioctl(this->bpf_fd, BIOCVERSION, (caddr_t)&bv) < 0) { - BX_PANIC(("eth_freebsd: could not retrieve bpf version")); - close(this->bpf_fd); - this->bpf_fd = -1; - return; - } - if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION) { - BX_PANIC(("eth_freebsd: bpf version mismatch between compilation and runtime")); - close(this->bpf_fd); - this->bpf_fd = -1; - return; - } - - // Set buffer size - v = BX_BPF_BUFSIZ; - if (ioctl(this->bpf_fd, BIOCSBLEN, (caddr_t)&v) < 0) { - BX_PANIC(("eth_freebsd: could not set buffer size: %s", strerror(errno))); - close(this->bpf_fd); - this->bpf_fd = -1; - return; - } - - (void)strncpy(ifr.ifr_name, netif, sizeof(ifr.ifr_name)); - if (ioctl(this->bpf_fd, BIOCSETIF, (caddr_t)&ifr) < 0) { - BX_PANIC(("eth_freebsd: could not enable interface '%s': %s", netif, strerror(errno))); - close(this->bpf_fd); - this->bpf_fd == -1; - } - - // Verify that the device is an ethernet. - if (ioctl(this->bpf_fd, BIOCGDLT, (caddr_t)&v) < 0) { - BX_PANIC(("eth_freebsd: could not retrieve datalink type: %s", strerror(errno))); - close(this->bpf_fd); - this->bpf_fd = -1; - return; - } - if (v != DLT_EN10MB) { - BX_PANIC(("eth_freebsd: incorrect datalink type %d, expected 10mb ethernet", v)); - close(this->bpf_fd); - this->bpf_fd = -1; - return; - } - - // Put the device into promisc mode. This could be optimised - // to filter on a MAC address, broadcast, and all-multi, - // but this will do for now. - // - if (ioctl(this->bpf_fd, BIOCPROMISC, NULL) < 0) { - BX_PANIC(("eth_freebsd: could not enable promisc mode: %s", strerror(errno))); - close(this->bpf_fd); - this->bpf_fd = -1; - return; - } - - // Set up non-blocking i/o - v = 1; - if (ioctl(this->bpf_fd, FIONBIO, &v) < 0) { - BX_PANIC(("eth_freebsd: could not enable non-blocking i/o: %s", strerror(errno))); - close(this->bpf_fd); - this->bpf_fd = -1; - return; - } - - // Install a filter -#ifdef notdef - memcpy(&this->filter, promiscfilter, sizeof(promiscfilter)); - bp.bf_len = 1; -#else - memcpy(&this->filter, macfilter, sizeof(macfilter)); - this->filter[1].k = - (macaddr[2] & 0xff) << 24 | - (macaddr[3] & 0xff) << 16 | - (macaddr[4] & 0xff) << 8 | - (macaddr[5] & 0xff); - this->filter[3].k = - (macaddr[0] & 0xff) << 8 | - (macaddr[1] & 0xff); - bp.bf_len = 8; -#endif - bp.bf_insns = &this->filter[0]; - if (ioctl(this->bpf_fd, BIOCSETF, &bp) < 0) { - BX_PANIC(("eth_freebsd: could not set filter: %s", strerror(errno))); - close(this->bpf_fd); - this->bpf_fd = -1; - return; - } - - // Start the rx poll - this->rx_timer_index = - bx_pc_system.register_timer(this, this->rx_timer_handler, BX_BPF_POLL, - 1, 1, "eth_fbsd"); // continuous, active - - this->rxh = rxh; - this->rxarg = rxarg; - -#if BX_ETH_FBSD_LOGGING - // eventually Bryce wants ne2klog to dump in pcap format so that - // tcpdump -r FILE can read it and interpret packets. - ne2klog = fopen ("ne2k.raw", "wb"); - if (!ne2klog) BX_PANIC (("open ne2k-tx.log failed")); - ne2klog_txt = fopen ("ne2k.txt", "wb"); - if (!ne2klog_txt) BX_PANIC (("open ne2k-txdump.txt failed")); - fprintf (ne2klog_txt, "null packetmover readable log file\n"); - fprintf (ne2klog_txt, "net IF = %s\n", netif); - fprintf (ne2klog_txt, "MAC address = "); - for (int i=0; i<6; i++) - fprintf (ne2klog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : ""); - fprintf (ne2klog_txt, "\n--\n"); - fflush (ne2klog_txt); -#endif -} - -// the output routine - called with pre-formatted ethernet frame. -void -bx_fbsd_pktmover_c::sendpkt(void *buf, unsigned io_len) -{ -#if BX_ETH_FBSD_LOGGING - BX_DEBUG (("sendpkt length %u", io_len)); - // dump raw bytes to a file, eventually dump in pcap format so that - // tcpdump -r FILE can interpret them for us. - int n = fwrite (buf, io_len, 1, ne2klog); - if (n != 1) BX_ERROR (("fwrite to ne2klog failed", io_len)); - // dump packet in hex into an ascii log file - fprintf (ne2klog_txt, "NE2K TX packet, length %u\n", io_len); - Bit8u *charbuf = (Bit8u *)buf; - for (n=0; n0) - fprintf (ne2klog_txt, "\n"); - fprintf (ne2klog_txt, "%02x ", charbuf[n]); - } - fprintf (ne2klog_txt, "\n--\n"); - // flush log so that we see the packets as they arrive w/o buffering - fflush (ne2klog); - fflush (ne2klog_txt); -#endif - int status; - - if (this->bpf_fd != -1) - status = write(this->bpf_fd, buf, io_len); -} - -// The receive poll process -void -bx_fbsd_pktmover_c::rx_timer_handler(void *this_ptr) -{ - bx_fbsd_pktmover_c *class_ptr = (bx_fbsd_pktmover_c *) this_ptr; - - class_ptr->rx_timer(); -} - - -void -bx_fbsd_pktmover_c::rx_timer(void) -{ - int nbytes = 0; - unsigned char rxbuf[BX_BPF_BUFSIZ]; - struct bpf_hdr *bhdr; - struct bpf_stat bstat; - static struct bpf_stat previous_bstat; - int counter = 10; -#define phdr ((unsigned char*)bhdr) - - bhdr = (struct bpf_hdr *) rxbuf; - nbytes = read(this->bpf_fd, rxbuf, sizeof(rxbuf)); - - while (phdr < (rxbuf + nbytes)) { - if (ioctl(this->bpf_fd, BIOCGSTATS, &bstat) < 0) { - BX_PANIC(("eth_freebsd: could not stat filter: %s", strerror(errno))); - } - if (bstat.bs_drop > previous_bstat.bs_drop) { - BX_INFO (("eth_freebsd: %d packets dropped by the kernel.", - bstat.bs_drop - previous_bstat.bs_drop)); - } - previous_bstat = bstat; - if (bhdr->bh_caplen < 20 || bhdr->bh_caplen > 1514) { - BX_ERROR(("eth_freebsd: received too weird packet length: %d", bhdr->bh_caplen)); - } - - // filter out packets sourced from this node - if (memcmp(bhdr + bhdr->bh_hdrlen + 6, this->fbsd_macaddr, 6)) { - (*rxh)(rxarg, phdr + bhdr->bh_hdrlen, bhdr->bh_caplen); - } - -#if BX_ETH_FBSD_LOGGING - /// hey wait there is no receive data with a NULL ethernet, is there.... - BX_DEBUG (("receive packet length %u", nbytes)); - // dump raw bytes to a file, eventually dump in pcap format so that - // tcpdump -r FILE can interpret them for us. - if (1 != fwrite (bhdr, bhdr->bh_caplen, 1, ne2klog)) { - BX_PANIC (("fwrite to ne2klog failed: %s", strerror(errno))); - } - // dump packet in hex into an ascii log file - fprintf (this->ne2klog_txt, "NE2K RX packet, length %u\n", bhdr->bh_caplen); - Bit8u *charrxbuf = (Bit8u *)rxbuf; - int n; - for (n=0; nbh_caplen; n++) { - if (((n % 16) == 0) && n>0) - fprintf (this->ne2klog_txt, "\n"); - fprintf (this->ne2klog_txt, "%02x ", phdr[n]); - } - fprintf (this->ne2klog_txt, "\n--\n"); - // flush log so that we see the packets as they arrive w/o buffering - fflush (this->ne2klog); - fflush (this->ne2klog_txt); -#endif - - // Advance bhdr and phdr pointers to next packet - bhdr = (struct bpf_hdr*) ((char*) bhdr + BPF_WORDALIGN(bhdr->bh_hdrlen + bhdr->bh_caplen)); - } -} - -#endif /* if BX_NE2K_SUPPORT && defined(ETH_FBSD) */ - diff --git a/tools/ioemu/iodev/eth_linux.cc b/tools/ioemu/iodev/eth_linux.cc deleted file mode 100644 index e7076b9e10..0000000000 --- a/tools/ioemu/iodev/eth_linux.cc +++ /dev/null @@ -1,286 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: eth_linux.cc,v 1.14 2003/02/16 19:35:57 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// Peter Grehan (grehan@iprg.nokia.com) coded all of this -// NE2000/ether stuff. - -// eth_linux.cc - A Linux socket filter adaptation of the FreeBSD BPF driver -// 21 June 2001 -// -// Problems and limitations: -// - packets cannot be sent from BOCHS to the host -// - Linux kernel sometimes gets network watchdog timeouts under emulation -// - author doesn't know C++ -// -// The config line in .bochsrc should look something like: -// -// ne2k: ioaddr=0x280, irq=10, mac=00:a:b:c:1:2, ethmod=linux, ethdev=eth0 -// - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_NE2K_SUPPORT && defined (ETH_LINUX) -#define LOG_THIS bx_devices.pluginNE2kDevice-> - -extern "C" { -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -}; - -#define BX_PACKET_POLL 1000 // Poll for a frame every 1000 usecs - -#define BX_PACKET_BUFSIZ 2048 // Enough for an ether frame - -// template filter for a unicast mac address and all -// multicast/broadcast frames -static const struct sock_filter macfilter[] = { - BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2), - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0xaaaaaaaa, 0, 2), - BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 0), - BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0000aaaa, 2, 0), - BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 0), - BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x01, 0, 1), - BPF_STMT(BPF_RET, 1514), - BPF_STMT(BPF_RET, 0), -}; -#define BX_LSF_ICNT 8 // number of lsf instructions in macfilter - -#if 0 -// template filter for all frames -static const struct sock_filter promiscfilter[] = { - BPF_STMT(BPF_RET, 1514) -}; -#endif - -// -// Define the class. This is private to this module -// -class bx_linux_pktmover_c : public eth_pktmover_c { -public: - bx_linux_pktmover_c(const char *netif, - const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg); - void sendpkt(void *buf, unsigned io_len); - -private: - unsigned char *linux_macaddr[6]; - int fd; - int ifindex; - static void rx_timer_handler(void *); - void rx_timer(void); - int rx_timer_index; - struct sock_filter filter[BX_LSF_ICNT]; -}; - - -// -// Define the static class that registers the derived pktmover class, -// and allocates one on request. -// -class bx_linux_locator_c : public eth_locator_c { -public: - bx_linux_locator_c(void) : eth_locator_c("linux") {} -protected: - eth_pktmover_c *allocate(const char *netif, - const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg) { - return (new bx_linux_pktmover_c(netif, macaddr, rxh, rxarg)); - } -} bx_linux_match; - - -// -// Define the methods for the bx_linux_pktmover derived class -// - -// the constructor -// -bx_linux_pktmover_c::bx_linux_pktmover_c(const char *netif, - const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg) -{ - struct sockaddr_ll sll; - struct packet_mreq mr; - struct ifreq ifr; - struct sock_fprog fp; - - memcpy(linux_macaddr, macaddr, 6); - - // Open packet socket - // - if ((this->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) { - if (errno == EACCES) - BX_PANIC(("eth_linux: must be root or have CAP_NET_RAW capability to open socket")); - else - BX_PANIC(("eth_linux: could not open socket: %s", strerror(errno))); - this->fd = -1; - return; - } - - // Translate interface name to index - // - memset(&ifr, 0, sizeof(ifr)); - strcpy(ifr.ifr_name, netif); - if (ioctl(this->fd, SIOCGIFINDEX, &ifr) == -1) { - BX_PANIC(("eth_linux: could not get index for interface '%s'\n", netif)); - close(fd); - this->fd = -1; - return; - } - this->ifindex = ifr.ifr_ifindex; - - - // Bind to given interface - // - memset(&sll, 0, sizeof(sll)); - sll.sll_family = AF_PACKET; - sll.sll_ifindex = this->ifindex; - if (bind(fd, (struct sockaddr *)&sll, (socklen_t)sizeof(sll)) == -1) { - BX_PANIC(("eth_linux: could not bind to interface '%s': %s\n", netif, strerror(errno))); - close(fd); - this->fd = -1; - return; - } - - // Put the device into promisc mode. - // - memset(&mr, 0, sizeof(mr)); - mr.mr_ifindex = this->ifindex; - mr.mr_type = PACKET_MR_PROMISC; - if (setsockopt(this->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (void *)&mr, (socklen_t)sizeof(mr)) == -1) { - BX_PANIC(("eth_linux: could not enable promisc mode: %s\n", strerror(errno))); - close(this->fd); - this->fd = -1; - return; - } - - // Set up non-blocking i/o - if (fcntl(this->fd, F_SETFL, O_NONBLOCK) == -1) { - BX_PANIC(("eth_linux: could not set non-blocking i/o on socket")); - close(this->fd); - this->fd = -1; - return; - } - - // Install a filter -#ifdef notdef - memcpy(&this->filter, promiscfilter, sizeof(promiscfilter)); - fp.len = 1; -#endif - memcpy(&this->filter, macfilter, sizeof(macfilter)); - this->filter[1].k = (macaddr[2] & 0xff) << 24 | (macaddr[3] & 0xff) << 16 | - (macaddr[4] & 0xff) << 8 | (macaddr[5] & 0xff); - this->filter[3].k = (macaddr[0] & 0xff) << 8 | (macaddr[1] & 0xff); - fp.len = BX_LSF_ICNT; - fp.filter = this->filter; - BX_INFO(("eth_linux: fp.len=%d fp.filter=%lx", fp.len, (unsigned long) fp.filter)); - if (setsockopt(this->fd, SOL_SOCKET, SO_ATTACH_FILTER, &fp, sizeof(fp)) < 0) { - BX_PANIC(("eth_linux: could not set socket filter: %s", strerror(errno))); - close(this->fd); - this->fd = -1; - return; - } - - // Start the rx poll - this->rx_timer_index = - bx_pc_system.register_timer(this, this->rx_timer_handler, BX_PACKET_POLL, - 1, 1, "eth_linux"); // continuous, active - - this->rxh = rxh; - this->rxarg = rxarg; - BX_INFO(("eth_linux: enabled NE2K emulation on interface %s", netif)); -} - -// the output routine - called with pre-formatted ethernet frame. -void -bx_linux_pktmover_c::sendpkt(void *buf, unsigned io_len) -{ - int status; - - if (this->fd != -1) { - status = write(this->fd, buf, io_len); - if (status == -1) - BX_INFO(("eth_linux: write failed: %s", strerror(errno))); - } -} - -// The receive poll process -void -bx_linux_pktmover_c::rx_timer_handler(void *this_ptr) -{ - bx_linux_pktmover_c *class_ptr = (bx_linux_pktmover_c *) this_ptr; - - class_ptr->rx_timer(); -} - -void -bx_linux_pktmover_c::rx_timer(void) -{ - int nbytes = 0; - Bit8u rxbuf[BX_PACKET_BUFSIZ]; - struct sockaddr_ll sll; - socklen_t fromlen; -//static unsigned char bcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; - - if (this->fd == -1) - return; - - fromlen = sizeof(sll); - nbytes = recvfrom(this->fd, rxbuf, sizeof(rxbuf), 0, (struct sockaddr *)&sll, &fromlen); - - if (nbytes == -1) { - if (errno != EAGAIN) - BX_INFO(("eth_linux: error receiving packet: %s\n", strerror(errno))); - return; - } - - // this should be done with LSF someday - // filter out packets sourced by us - if (memcmp(sll.sll_addr, this->linux_macaddr, 6) == 0) - return; - // let through broadcast, multicast, and our mac address -// if ((memcmp(rxbuf, bcast_addr, 6) == 0) || (memcmp(rxbuf, this->linux_macaddr, 6) == 0) || rxbuf[0] & 0x01) { - BX_DEBUG(("eth_linux: got packet: %d bytes, dst=%x:%x:%x:%x:%x:%x, src=%x:%x:%x:%x:%x:%x\n", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11])); - (*rxh)(rxarg, rxbuf, nbytes); -// } -} -#endif /* if BX_NE2K_SUPPORT && defined ETH_LINUX */ diff --git a/tools/ioemu/iodev/eth_null.cc b/tools/ioemu/iodev/eth_null.cc deleted file mode 100644 index 11162798ef..0000000000 --- a/tools/ioemu/iodev/eth_null.cc +++ /dev/null @@ -1,164 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: eth_null.cc,v 1.13 2002/11/20 19:06:23 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// eth_null.cc - skeleton code for an ethernet pktmover - -// Various networking docs: -// http://www.graphcomp.com/info/rfc/ -// rfc0826: arp -// rfc0903: rarp - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_NE2K_SUPPORT - -#define LOG_THIS bx_devices.pluginNE2kDevice-> - - -// -// Define the class. This is private to this module -// -class bx_null_pktmover_c : public eth_pktmover_c { -public: - bx_null_pktmover_c(const char *netif, const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg); - void sendpkt(void *buf, unsigned io_len); -private: - int rx_timer_index; - static void rx_timer_handler(void *); - FILE *txlog, *txlog_txt, *rxlog, *rxlog_txt; -}; - - -// -// Define the static class that registers the derived pktmover class, -// and allocates one on request. -// -class bx_null_locator_c : public eth_locator_c { -public: - bx_null_locator_c(void) : eth_locator_c("null") {} -protected: - eth_pktmover_c *allocate(const char *netif, const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg) { - return (new bx_null_pktmover_c(netif, macaddr, rxh, rxarg)); - } -} bx_null_match; - - -// -// Define the methods for the bx_null_pktmover derived class -// - -// the constructor -bx_null_pktmover_c::bx_null_pktmover_c(const char *netif, - const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg) -{ -#if BX_ETH_NULL_LOGGING - // Start the rx poll - this->rx_timer_index = - bx_pc_system.register_timer(this, this->rx_timer_handler, 1000, - 1, 1, "eth_null"); // continuous, active - this->rxh = rxh; - this->rxarg = rxarg; - // eventually Bryce wants txlog to dump in pcap format so that - // tcpdump -r FILE can read it and interpret packets. - txlog = fopen ("ne2k-tx.log", "wb"); - if (!txlog) BX_PANIC (("open ne2k-tx.log failed")); - txlog_txt = fopen ("ne2k-txdump.txt", "wb"); - if (!txlog_txt) BX_PANIC (("open ne2k-txdump.txt failed")); - fprintf (txlog_txt, "null packetmover readable log file\n"); - fprintf (txlog_txt, "net IF = %s\n", netif); - fprintf (txlog_txt, "MAC address = "); - for (int i=0; i<6; i++) - fprintf (txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : ""); - fprintf (txlog_txt, "\n--\n"); - fflush (txlog_txt); -#endif -} - -void -bx_null_pktmover_c::sendpkt(void *buf, unsigned io_len) -{ -#if BX_ETH_NULL_LOGGING - BX_DEBUG (("sendpkt length %u", io_len)); - // dump raw bytes to a file, eventually dump in pcap format so that - // tcpdump -r FILE can interpret them for us. - unsigned int n = fwrite (buf, io_len, 1, txlog); - if (n != 1) BX_ERROR (("fwrite to txlog failed, io_len = %u", io_len)); - // dump packet in hex into an ascii log file - fprintf (txlog_txt, "NE2K transmitting a packet, length %u\n", io_len); - Bit8u *charbuf = (Bit8u *)buf; - for (n=0; n0) - fprintf (txlog_txt, "\n"); - fprintf (txlog_txt, "%02x ", charbuf[n]); - } - fprintf (txlog_txt, "\n--\n"); - // flush log so that we see the packets as they arrive w/o buffering - fflush (txlog); - fflush (txlog_txt); -#endif -} - -void bx_null_pktmover_c::rx_timer_handler (void *this_ptr) -{ -#if BX_ETH_NULL_LOGGING - /// hey wait there is no receive data with a NULL ethernet, is there.... - - int io_len = 0; - Bit8u buf[1]; - bx_null_pktmover_c *class_ptr = (bx_null_pktmover_c *) this_ptr; - if (io_len > 0) { - BX_DEBUG (("receive packet length %u", io_len)); - // dump raw bytes to a file, eventually dump in pcap format so that - // tcpdump -r FILE can interpret them for us. - int n = fwrite (buf, io_len, 1, class_ptr->rxlog); - if (n != 1) BX_ERROR (("fwrite to rxlog failed, io_len = %u", io_len)); - // dump packet in hex into an ascii log file - fprintf (class_ptr->rxlog_txt, "NE2K transmitting a packet, length %u\n", io_len); - Bit8u *charbuf = (Bit8u *)buf; - for (n=0; n0) - fprintf (class_ptr->rxlog_txt, "\n"); - fprintf (class_ptr->rxlog_txt, "%02x ", charbuf[n]); - } - fprintf (class_ptr->rxlog_txt, "\n--\n"); - // flush log so that we see the packets as they arrive w/o buffering - fflush (class_ptr->rxlog); - fflush (class_ptr->rxlog_txt); - } -#endif -} - -#endif /* if BX_NE2K_SUPPORT */ diff --git a/tools/ioemu/iodev/eth_packetmaker.cc b/tools/ioemu/iodev/eth_packetmaker.cc deleted file mode 100644 index 5ed5e47c8c..0000000000 --- a/tools/ioemu/iodev/eth_packetmaker.cc +++ /dev/null @@ -1,184 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: eth_packetmaker.cc,v 1.8 2002/11/20 19:06:23 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" - -#if BX_NE2K_SUPPORT && defined(ETH_ARPBACK) - -#include "eth_packetmaker.h" - - -bx_bool sendable(const eth_packet& outpacket) { - //FINISH ME! -} - -Bit32u eth_IPmaker::datalen(const eth_packet& outpacket) { - Bit32u out; - out=((outpacket.buf[16]<<8)+outpacket.buf[17])-(4*(0xF & outpacket.buf[14])); - return out; -} - -const Bit8u * eth_IPmaker::datagram(const eth_packet& outpacket) { - const Bit8u * out; - out=outpacket.buf+14+(4*(0xF & outpacket.buf[14])); - return out; -} - -Bit32u eth_IPmaker::build_packet_header(Bit32u source, Bit32u dest, Bit8u protocol, Bit32u datalen) { - Bit32u temp; - Bit32u i; - memcpy(pending.buf,internal_mac,6); - memcpy(pending.buf+6,external_mac,6); - memcpy(pending.buf+12,ethtype_ip,2); - pending.buf[14]=0x45; - pending.buf[15]=0; - temp=datalen+20; - pending.buf[16]=(temp>>8) & 0xFF; - pending.buf[17]=temp & 0xFF; - pending.buf[18]=0; - pending.buf[19]=0; - pending.buf[20]=0; - pending.buf[21]=0; - pending.buf[22]=30; - pending.buf[23]=protocol; - pending.buf[24]=0; - pending.buf[25]=0; - pending.buf[26]=(source>>24) & 0xFF; - pending.buf[27]=(source>>16) & 0xFF; - pending.buf[28]=(source>>8) & 0xFF; - pending.buf[29]=(source) & 0xFF; - pending.buf[30]=(dest>>24) & 0xFF; - pending.buf[31]=(dest>>16) & 0xFF; - pending.buf[32]=(dest>>8) & 0xFF; - pending.buf[33]=(dest) & 0xFF; - //Compute Checksum - temp=0; - for(i=14;i<34;i=i+2) { - Bit32u addee=pending.buf[i]; - addee=(addee<<8) & pending.buf[i+1]; - temp=temp+addee; - } - temp=(temp>>16)+(temp&0xFFFF); - temp=(temp>>16)+(temp&0xFFFF); - pending.buf[24]=~(Bit8u)((temp>>8) & 0xFF); - pending.buf[25]=~(Bit8u)(temp & 0xFF); - return(34); -} - -Bit8u eth_IPmaker::protocol(const eth_packet& outpacket) { - Bit8u out; - out=0xFF & *(outpacket.buf+23); -} - -Bit32u eth_IPmaker::source(const eth_packet& outpacket) { - Bit32u out; - out=0xFF & *(outpacket.buf+26); - out=(out<<8) | (0xFF & *(outpacket.buf+27)); - out=(out<<8) | (0xFF & *(outpacket.buf+28)); - out=(out<<8) | (0xFF & *(outpacket.buf+29)); - return out; -} - -Bit32u eth_IPmaker::destination(const eth_packet& outpacket) { - Bit32u out; - out=0xFF & *(outpacket.buf+30); - out=(out<<8) | (0xFF & *(outpacket.buf+31)); - out=(out<<8) | (0xFF & *(outpacket.buf+32)); - out=(out<<8) | (0xFF & *(outpacket.buf+33)); - return out; -} - -void eth_IPmaker::init(void) { - is_pending=0; -} - -void -eth_ETHmaker::init(void) { - arper.init(); -} - -bx_bool -eth_ETHmaker::getpacket(eth_packet& inpacket) { - return arper.getpacket(inpacket); -} - -bx_bool -eth_ETHmaker::ishandler(const eth_packet& outpacket) { - if((outpacket.len>=60) && - ( (!memcmp(outpacket.buf, external_mac, 6)) - || (!memcmp(outpacket.buf, broadcast_mac, 6)) ) && - ( (!memcmp(outpacket.buf+12, ethtype_arp, 2)) || - (!memcmp(outpacket.buf+12, ethtype_ip, 2)) ) && - (outpacket.len=60) && - (!memcmp(outpacket.buf+12, ethtype_arp, 2)) && - (outpacket.len 10.0.0.2: icmp: echo request -// 4500 0054 2800 0000 4001 3ea7 0a00 0001 -// 0a00 0002 0800 09d3 a53e 0400 9765 893c -// 3949 0000 0809 0a0b 0c0d 0e0f 1011 1213 -// 1415 1617 1819 -// 20:29:59.023017 fe:fd:0:0:0:1 fe:fd:0:0:0:0 0800 98: 10.0.0.2 > 10.0.0.1: icmp: echo reply -// 4500 0054 004a 0000 4001 665d 0a00 0002 -// 0a00 0001 0000 11d3 a53e 0400 9765 893c -// 3949 0000 0809 0a0b 0c0d 0e0f 1011 1213 -// 1415 1617 1819 -// -// I suspect it may be related to the fact that ping 10.0.0.1 from the -// host also doesn't work. Why wouldn't the host respond to its own IP -// address on the tap0 device? -// -// Theoretically, if you set up packet forwarding (with masquerading) on the -// host, you should be able to get Bochs talking to anyone on the internet. -// - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_NE2K_SUPPORT - -#define LOG_THIS bx_devices.pluginNE2kDevice-> - -#include -#include -#include -#ifndef __APPLE__ -#include -#endif -#include -#include -#include -#include -#include -#if defined(__FreeBSD__) || defined(__APPLE__) // Should be fixed for other *BSD -#include -#else -#include -#include -#include -#endif -#include -#include -#include - -#define TAP_VIRTUAL_HW_ADDR 0xDEADBEEF -#define BX_ETH_TAP_LOGGING 1 -#define BX_PACKET_BUFSIZ 2048 // Enough for an ether frame - -// -// Define the class. This is private to this module -// -class bx_tap_pktmover_c : public eth_pktmover_c { -public: - bx_tap_pktmover_c(const char *netif, const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg); - void sendpkt(void *buf, unsigned io_len); -private: - int fd; - int rx_timer_index; - static void rx_timer_handler(void *); - void rx_timer (); - FILE *txlog, *txlog_txt, *rxlog, *rxlog_txt; -}; - - -// -// Define the static class that registers the derived pktmover class, -// and allocates one on request. -// -class bx_tap_locator_c : public eth_locator_c { -public: - bx_tap_locator_c(void) : eth_locator_c("tap") {} -protected: - eth_pktmover_c *allocate(const char *netif, const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg) { - return (new bx_tap_pktmover_c(netif, macaddr, rxh, rxarg)); - } -} bx_tap_match; - - -// -// Define the methods for the bx_tap_pktmover derived class -// - -// the constructor -bx_tap_pktmover_c::bx_tap_pktmover_c(const char *netif, - const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg) -{ - int flags; - char filename[BX_PATHNAME_LEN]; - if (strncmp (netif, "tap", 3) != 0) { - BX_PANIC (("eth_tap: interface name (%s) must be tap0..tap15", netif)); - } - sprintf (filename, "/dev/%s", netif); - -#if defined(__linux__) - // check if the TAP devices is running, and turn on ARP. This is based - // on code from the Mac-On-Linux project. http://http://www.maconlinux.org/ - int sock = socket( AF_INET, SOCK_DGRAM, 0 ); - if (sock < 0) { - BX_PANIC (("socket creation: %s", strerror(errno))); - return; - } - struct ifreq ifr; - memset( &ifr, 0, sizeof(ifr) ); - strncpy( ifr.ifr_name, netif, sizeof(ifr.ifr_name) ); - if( ioctl( sock, SIOCGIFFLAGS, &ifr ) < 0 ){ - BX_PANIC (("SIOCGIFFLAGS on %s: %s", netif, strerror (errno))); - close(sock); - return; - } - if( !(ifr.ifr_flags & IFF_RUNNING ) ){ - BX_PANIC (("%s device is not running", netif)); - close(sock); - return; - } - if( (ifr.ifr_flags & IFF_NOARP ) ){ - BX_INFO (("turn on ARP for %s device", netif)); - ifr.ifr_flags &= ~IFF_NOARP; - if( ioctl( sock, SIOCSIFFLAGS, &ifr ) < 0 ) { - BX_PANIC (("SIOCSIFFLAGS: %s", strerror(errno))); - close(sock); - return; - } - } - close(sock); -#endif - - fd = open (filename, O_RDWR); - if (fd < 0) { - BX_PANIC (("open failed on %s: %s", netif, strerror (errno))); - return; - } - - /* set O_ASYNC flag so that we can poll with read() */ - if ((flags = fcntl( fd, F_GETFL)) < 0) { - BX_PANIC (("getflags on tap device: %s", strerror (errno))); - } - flags |= O_NONBLOCK; - if (fcntl( fd, F_SETFL, flags ) < 0) { - BX_PANIC (("set tap device flags: %s", strerror (errno))); - } - - BX_INFO (("eth_tap: opened %s device", netif)); - - /* Execute the configuration script */ - char intname[IFNAMSIZ]; - strcpy(intname,netif); - char *scriptname=bx_options.ne2k.Oscript->getptr(); - if((scriptname != NULL) - &&(strcmp(scriptname, "") != 0) - &&(strcmp(scriptname, "none") != 0)) { - if (execute_script(scriptname, intname) < 0) - BX_ERROR (("execute script '%s' on %s failed", scriptname, intname)); - } - - // Start the rx poll - this->rx_timer_index = - bx_pc_system.register_timer(this, this->rx_timer_handler, 1000, - 1, 1, "eth_tap"); // continuous, active - this->rxh = rxh; - this->rxarg = rxarg; -#if BX_ETH_TAP_LOGGING - // eventually Bryce wants txlog to dump in pcap format so that - // tcpdump -r FILE can read it and interpret packets. - txlog = fopen ("ne2k-tx.log", "wb"); - if (!txlog) BX_PANIC (("open ne2k-tx.log failed")); - txlog_txt = fopen ("ne2k-txdump.txt", "wb"); - if (!txlog_txt) BX_PANIC (("open ne2k-txdump.txt failed")); - fprintf (txlog_txt, "tap packetmover readable log file\n"); - fprintf (txlog_txt, "net IF = %s\n", netif); - fprintf (txlog_txt, "MAC address = "); - for (int i=0; i<6; i++) - fprintf (txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : ""); - fprintf (txlog_txt, "\n--\n"); - fflush (txlog_txt); - - rxlog = fopen ("ne2k-rx.log", "wb"); - if (!rxlog) BX_PANIC (("open ne2k-rx.log failed")); - rxlog_txt = fopen ("ne2k-rxdump.txt", "wb"); - if (!rxlog_txt) BX_PANIC (("open ne2k-rxdump.txt failed")); - fprintf (rxlog_txt, "tap packetmover readable log file\n"); - fprintf (rxlog_txt, "net IF = %s\n", netif); - fprintf (rxlog_txt, "MAC address = "); - for (int i=0; i<6; i++) - fprintf (rxlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : ""); - fprintf (rxlog_txt, "\n--\n"); - fflush (rxlog_txt); - -#endif -} - -void -bx_tap_pktmover_c::sendpkt(void *buf, unsigned io_len) -{ - Bit8u txbuf[BX_PACKET_BUFSIZ]; - txbuf[0] = 0; - txbuf[1] = 0; -#if defined(__FreeBSD__) || defined(__APPLE__) // Should be fixed for other *BSD - memcpy (txbuf, buf, io_len); - unsigned int size = write (fd, txbuf, io_len); - if (size != io_len) { -#else - memcpy (txbuf+2, buf, io_len); - unsigned int size = write (fd, txbuf, io_len+2); - if (size != io_len+2) { -#endif - BX_PANIC (("write on tap device: %s", strerror (errno))); - } else { - BX_INFO (("wrote %d bytes + 2 byte pad on tap", io_len)); - } -#if BX_ETH_TAP_LOGGING - BX_DEBUG (("sendpkt length %u", io_len)); - // dump raw bytes to a file, eventually dump in pcap format so that - // tcpdump -r FILE can interpret them for us. - int n = fwrite (buf, io_len, 1, txlog); - if (n != 1) BX_ERROR (("fwrite to txlog failed, io_len = %u", io_len)); - // dump packet in hex into an ascii log file - fprintf (txlog_txt, "NE2K transmitting a packet, length %u\n", io_len); - Bit8u *charbuf = (Bit8u *)buf; - for (n=0; n<(int)io_len; n++) { - if (((n % 16) == 0) && n>0) - fprintf (txlog_txt, "\n"); - fprintf (txlog_txt, "%02x ", charbuf[n]); - } - fprintf (txlog_txt, "\n--\n"); - // flush log so that we see the packets as they arrive w/o buffering - fflush (txlog); - fflush (txlog_txt); -#endif -} - -void bx_tap_pktmover_c::rx_timer_handler (void *this_ptr) -{ - bx_tap_pktmover_c *class_ptr = (bx_tap_pktmover_c *) this_ptr; - class_ptr->rx_timer(); -} - -void bx_tap_pktmover_c::rx_timer () -{ - int nbytes; - Bit8u buf[BX_PACKET_BUFSIZ]; - Bit8u *rxbuf; - if (fd<0) return; - nbytes = read (fd, buf, sizeof(buf)); - - // hack: discard first two bytes -#if defined(__FreeBSD__) || defined(__APPLE__) // Should be fixed for other *BSD - rxbuf = buf; -#else - rxbuf = buf+2; - nbytes-=2; -#endif - - // hack: TAP device likes to create an ethernet header which has - // the same source and destination address FE:FD:00:00:00:00. - // Change the dest address to FE:FD:00:00:00:01. -#if defined(__linux__) - rxbuf[5] = 1; -#endif - - if (nbytes>0) - BX_INFO (("tap read returned %d bytes", nbytes)); - if (nbytes<0) { - if (errno != EAGAIN) - BX_ERROR (("tap read error: %s", strerror(errno))); - return; - } -#if BX_ETH_TAP_LOGGING - if (nbytes > 0) { - BX_DEBUG (("receive packet length %u", nbytes)); - // dump raw bytes to a file, eventually dump in pcap format so that - // tcpdump -r FILE can interpret them for us. - int n = fwrite (rxbuf, nbytes, 1, rxlog); - if (n != 1) BX_ERROR (("fwrite to rxlog failed, nbytes = %d", nbytes)); - // dump packet in hex into an ascii log file - fprintf (rxlog_txt, "NE2K received a packet, length %u\n", nbytes); - for (n=0; n0) - fprintf (rxlog_txt, "\n"); - fprintf (rxlog_txt, "%02x ", rxbuf[n]); - } - fprintf (rxlog_txt, "\n--\n"); - // flush log so that we see the packets as they arrive w/o buffering - fflush (rxlog); - fflush (rxlog_txt); - } -#endif - BX_DEBUG(("eth_tap: got packet: %d bytes, dst=%x:%x:%x:%x:%x:%x, src=%x:%x:%x:%x:%x:%x\n", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11])); - if (nbytes < 60) { - BX_INFO (("packet too short (%d), padding to 60", nbytes)); - nbytes = 60; - } - (*rxh)(rxarg, rxbuf, nbytes); -} - -#endif /* if BX_NE2K_SUPPORT */ diff --git a/tools/ioemu/iodev/eth_tuntap.cc b/tools/ioemu/iodev/eth_tuntap.cc deleted file mode 100644 index f910fd55f1..0000000000 --- a/tools/ioemu/iodev/eth_tuntap.cc +++ /dev/null @@ -1,401 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: eth_tuntap.cc,v 1.9 2003/04/26 14:48:45 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// eth_tuntap.cc - TUN/TAP interface by Renzo Davoli -// -// WARNING: These instructions were written for ethertap, not TUN/TAP. -// -// Here's how to get this working. On the host machine: -// $ su root -// # /sbin/insmod ethertap -// Using /lib/modules/2.2.14-5.0/net/ethertap.o -// # mknod /dev/tap0 c 36 16 # if not already there -// # /sbin/ifconfig tap0 10.0.0.1 -// # /sbin/route add -host 10.0.0.2 gw 10.0.0.1 -// -// Now you have a tap0 device which you can on the ifconfig output. The -// tap0 interface has the IP address of 10.0.0.1. The bochs machine will have -// the IP address 10.0.0.2. -// -// Compile a bochs version from March 8, 2002 or later with --enable-ne2000. -// Add this ne2k line to your .bochsrc to activate the tap device. -// ne2k: ioaddr=0x280, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0 -// Don't change the mac or ethmod! -// -// Boot up DLX Linux in Bochs. Log in as root and then type the following -// commands to set up networking: -// # ifconfig eth0 10.0.0.2 -// # route add -net 10.0.0.0 -// # route add default gw 10.0.0.1 -// Now you should be able to ping from guest OS to your host machine, if -// you give its IP number. I'm still having trouble with pings from the -// host machine to the guest, so something is still not right. Symptoms: I -// ping from the host to the guest's IP address 10.0.0.2. With tcpdump I can -// see the ping going to Bochs, and then the ping reply coming from Bochs. -// But the ping program itself does not see the responses....well every -// once in a while it does, like 1 in 60 pings. -// -// host$ ping 10.0.0.2 -// PING 10.0.0.2 (10.0.0.2) from 10.0.0.1 : 56(84) bytes of data. -// -// Netstat output: -// 20:29:59.018776 fe:fd:0:0:0:0 fe:fd:0:0:0:1 0800 98: 10.0.0.1 > 10.0.0.2: icmp: echo request -// 4500 0054 2800 0000 4001 3ea7 0a00 0001 -// 0a00 0002 0800 09d3 a53e 0400 9765 893c -// 3949 0000 0809 0a0b 0c0d 0e0f 1011 1213 -// 1415 1617 1819 -// 20:29:59.023017 fe:fd:0:0:0:1 fe:fd:0:0:0:0 0800 98: 10.0.0.2 > 10.0.0.1: icmp: echo reply -// 4500 0054 004a 0000 4001 665d 0a00 0002 -// 0a00 0001 0000 11d3 a53e 0400 9765 893c -// 3949 0000 0809 0a0b 0c0d 0e0f 1011 1213 -// 1415 1617 1819 -// -// I suspect it may be related to the fact that ping 10.0.0.1 from the -// host also doesn't work. Why wouldn't the host respond to its own IP -// address on the tap0 device? -// -// Theoretically, if you set up packet forwarding (with masquerading) on the -// host, you should be able to get Bochs talking to anyone on the internet. -// - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_NE2K_SUPPORT - -#define LOG_THIS bx_devices.pluginNE2kDevice-> - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TUNTAP_VIRTUAL_HW_ADDR 0xDEADBEEF -#define BX_ETH_TUNTAP_LOGGING 0 -#define BX_PACKET_BUFSIZ 2048 // Enough for an ether frame - -int tun_alloc(char *dev); - -// -// Define the class. This is private to this module -// -class bx_tuntap_pktmover_c : public eth_pktmover_c { -public: - bx_tuntap_pktmover_c(const char *netif, const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg); - void sendpkt(void *buf, unsigned io_len); -private: - int fd; - int rx_timer_index; - static void rx_timer_handler(void *); - void rx_timer (); - FILE *txlog, *txlog_txt, *rxlog, *rxlog_txt; -}; - - -// -// Define the static class that registers the derived pktmover class, -// and allocates one on request. -// -class bx_tuntap_locator_c : public eth_locator_c { -public: - bx_tuntap_locator_c(void) : eth_locator_c("tuntap") {} -protected: - eth_pktmover_c *allocate(const char *netif, const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg) { - return (new bx_tuntap_pktmover_c(netif, macaddr, rxh, rxarg)); - } -} bx_tuntap_match; - - -// -// Define the methods for the bx_tuntap_pktmover derived class -// - -// the constructor -bx_tuntap_pktmover_c::bx_tuntap_pktmover_c(const char *netif, - const char *macaddr, - eth_rx_handler_t rxh, - void *rxarg) -{ - int flags; - if (strncmp (netif, "tun", 3) != 0) { - BX_PANIC (("eth_tuntap: interface name (%s) must be tun", netif)); - } -#ifdef NEVERDEF - char filename[BX_PATHNAME_LEN]; - sprintf (filename, "/dev/net/%s", netif); - - // check if the TUN/TAP devices is running, and turn on ARP. This is based - // on code from the Mac-On-Linux project. http://http://www.maconlinux.org/ - int sock = socket( AF_INET, SOCK_DGRAM, 0 ); - if (sock < 0) { - BX_PANIC (("socket creation: %s", strerror(errno))); - return; - } - struct ifreq ifr; - memset( &ifr, 0, sizeof(ifr) ); - strncpy( ifr.ifr_name, netif, sizeof(ifr.ifr_name) ); - if( ioctl( sock, SIOCGIFFLAGS, &ifr ) < 0 ){ - BX_PANIC (("SIOCGIFFLAGS on %s: %s", netif, strerror (errno))); - close(sock); - return; - } - if( !(ifr.ifr_flags & IFF_RUNNING ) ){ - BX_PANIC (("%s device is not running", netif)); - close(sock); - return; - } - if( (ifr.ifr_flags & IFF_NOARP ) ){ - BX_INFO (("turn on ARP for %s device", netif)); - ifr.ifr_flags &= ~IFF_NOARP; - if( ioctl( sock, SIOCSIFFLAGS, &ifr ) < 0 ) { - BX_PANIC (("SIOCSIFFLAGS: %s", strerror(errno))); - close(sock); - return; - } - } - close(sock); - - fd = open (filename, O_RDWR); -#endif - char intname[IFNAMSIZ]; - strcpy(intname,netif); - fd=tun_alloc(intname); - if (fd < 0) { - BX_PANIC (("open failed on %s: %s", netif, strerror (errno))); - return; - } - - /* set O_ASYNC flag so that we can poll with read() */ - if ((flags = fcntl( fd, F_GETFL)) < 0) { - BX_PANIC (("getflags on tun device: %s", strerror (errno))); - } - flags |= O_NONBLOCK; - if (fcntl( fd, F_SETFL, flags ) < 0) { - BX_PANIC (("set tun device flags: %s", strerror (errno))); - } - - BX_INFO (("eth_tuntap: opened %s device", netif)); - - /* Execute the configuration script */ - char *scriptname=bx_options.ne2k.Oscript->getptr(); - if((scriptname != NULL) - &&(strcmp(scriptname, "") != 0) - &&(strcmp(scriptname, "none") != 0)) { - if (execute_script(scriptname, intname) < 0) - BX_ERROR (("execute script '%s' on %s failed", scriptname, intname)); - } - - // Start the rx poll - this->rx_timer_index = - bx_pc_system.register_timer(this, this->rx_timer_handler, 1000, - 1, 1, "eth_tuntap"); // continuous, active - this->rxh = rxh; - this->rxarg = rxarg; -#if BX_ETH_TUNTAP_LOGGING - // eventually Bryce wants txlog to dump in pcap format so that - // tcpdump -r FILE can read it and interpret packets. - txlog = fopen ("ne2k-tx.log", "wb"); - if (!txlog) BX_PANIC (("open ne2k-tx.log failed")); - txlog_txt = fopen ("ne2k-txdump.txt", "wb"); - if (!txlog_txt) BX_PANIC (("open ne2k-txdump.txt failed")); - fprintf (txlog_txt, "tuntap packetmover readable log file\n"); - fprintf (txlog_txt, "net IF = %s\n", netif); - fprintf (txlog_txt, "MAC address = "); - for (int i=0; i<6; i++) - fprintf (txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : ""); - fprintf (txlog_txt, "\n--\n"); - fflush (txlog_txt); - - rxlog = fopen ("ne2k-rx.log", "wb"); - if (!rxlog) BX_PANIC (("open ne2k-rx.log failed")); - rxlog_txt = fopen ("ne2k-rxdump.txt", "wb"); - if (!rxlog_txt) BX_PANIC (("open ne2k-rxdump.txt failed")); - fprintf (rxlog_txt, "tuntap packetmover readable log file\n"); - fprintf (rxlog_txt, "net IF = %s\n", netif); - fprintf (rxlog_txt, "MAC address = "); - for (int i=0; i<6; i++) - fprintf (rxlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : ""); - fprintf (rxlog_txt, "\n--\n"); - fflush (rxlog_txt); - -#endif -} - -void -bx_tuntap_pktmover_c::sendpkt(void *buf, unsigned io_len) -{ -#ifdef NEVERDEF - Bit8u txbuf[BX_PACKET_BUFSIZ]; - txbuf[0] = 0; - txbuf[1] = 0; - memcpy (txbuf+2, buf, io_len); - unsigned int size = write (fd, txbuf, io_len+2); - if (size != io_len+2) { - BX_PANIC (("write on tuntap device: %s", strerror (errno))); - } else { - BX_INFO (("wrote %d bytes + 2 byte pad on tuntap", io_len)); - } -#endif - unsigned int size = write (fd, buf, io_len); - if (size != io_len) { - BX_PANIC (("write on tuntap device: %s", strerror (errno))); - } else { - BX_INFO (("wrote %d bytes on tuntap", io_len)); - } -#if BX_ETH_TUNTAP_LOGGING - BX_DEBUG (("sendpkt length %u", io_len)); - // dump raw bytes to a file, eventually dump in pcap format so that - // tcpdump -r FILE can interpret them for us. - int n = fwrite (buf, io_len, 1, txlog); - if (n != 1) BX_ERROR (("fwrite to txlog failed", io_len)); - // dump packet in hex into an ascii log file - fprintf (txlog_txt, "NE2K transmitting a packet, length %u\n", io_len); - Bit8u *charbuf = (Bit8u *)buf; - for (n=0; n0) - fprintf (txlog_txt, "\n"); - fprintf (txlog_txt, "%02x ", charbuf[n]); - } - fprintf (txlog_txt, "\n--\n"); - // flush log so that we see the packets as they arrive w/o buffering - fflush (txlog); - fflush (txlog_txt); -#endif -} - -void bx_tuntap_pktmover_c::rx_timer_handler (void *this_ptr) -{ - bx_tuntap_pktmover_c *class_ptr = (bx_tuntap_pktmover_c *) this_ptr; - class_ptr->rx_timer(); -} - -void bx_tuntap_pktmover_c::rx_timer () -{ - int nbytes; - Bit8u buf[BX_PACKET_BUFSIZ]; - Bit8u *rxbuf; - if (fd<0) return; - nbytes = read (fd, buf, sizeof(buf)); - -#ifdef NEVERDEF - // hack: discard first two bytes - rxbuf = buf+2; - nbytes-=2; -#else - rxbuf=buf; -#endif - - // hack: TUN/TAP device likes to create an ethernet header which has - // the same source and destination address FE:FD:00:00:00:00. - // Change the dest address to FE:FD:00:00:00:01. - rxbuf[5] = 1; - - if (nbytes>0) - BX_INFO (("tuntap read returned %d bytes", nbytes)); - if (nbytes<0) { - if (errno != EAGAIN) - BX_ERROR (("tuntap read error: %s", strerror(errno))); - return; - } -#if BX_ETH_TUNTAP_LOGGING - if (nbytes > 0) { - BX_DEBUG (("receive packet length %u", nbytes)); - // dump raw bytes to a file, eventually dump in pcap format so that - // tcpdump -r FILE can interpret them for us. - int n = fwrite (rxbuf, nbytes, 1, rxlog); - if (n != 1) BX_ERROR (("fwrite to rxlog failed", nbytes)); - // dump packet in hex into an ascii log file - fprintf (rxlog_txt, "NE2K received a packet, length %u\n", nbytes); - for (n=0; n0) - fprintf (rxlog_txt, "\n"); - fprintf (rxlog_txt, "%02x ", rxbuf[n]); - } - fprintf (rxlog_txt, "\n--\n"); - // flush log so that we see the packets as they arrive w/o buffering - fflush (rxlog); - fflush (rxlog_txt); - } -#endif - BX_DEBUG(("eth_tuntap: got packet: %d bytes, dst=%x:%x:%x:%x:%x:%x, src=%x:%x:%x:%x:%x:%x\n", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11])); - if (nbytes < 60) { - BX_INFO (("packet too short (%d), padding to 60", nbytes)); - nbytes = 60; - } - (*rxh)(rxarg, rxbuf, nbytes); -} - - - int tun_alloc(char *dev) - { - struct ifreq ifr; - int fd, err; - - if( (fd = open("/dev/net/tun", O_RDWR)) < 0 ) - return -1; - - memset(&ifr, 0, sizeof(ifr)); - - /* Flags: IFF_TUN - TUN device (no Ethernet headers) - * IFF_TAP - TAP device - * - * IFF_NO_PI - Do not provide packet information - */ - ifr.ifr_flags = IFF_TAP | IFF_NO_PI; - if( *dev ) - strncpy(ifr.ifr_name, dev, IFNAMSIZ); - - if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){ - close(fd); - return err; - } - - //strcpy(dev, ifr.ifr_name); - ioctl( fd, TUNSETNOCSUM, 1 ); - - return fd; - } - -#endif /* if BX_NE2K_SUPPORT */ diff --git a/tools/ioemu/iodev/extfpuirq.cc b/tools/ioemu/iodev/extfpuirq.cc deleted file mode 100644 index 5d1ed986bf..0000000000 --- a/tools/ioemu/iodev/extfpuirq.cc +++ /dev/null @@ -1,107 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: extfpuirq.cc,v 1.5 2003/07/31 12:04:48 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// -// External circuit for MSDOS compatible FPU exceptions -// - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" - -#define LOG_THIS theExternalFpuIrq-> - -bx_extfpuirq_c *theExternalFpuIrq = NULL; - - int -libextfpuirq_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - theExternalFpuIrq = new bx_extfpuirq_c (); - bx_devices.pluginExtFpuIrq = theExternalFpuIrq; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theExternalFpuIrq, BX_PLUGIN_EXTFPUIRQ); - return(0); // Success -} - - void -libextfpuirq_LTX_plugin_fini(void) -{ -} - -bx_extfpuirq_c::bx_extfpuirq_c(void) -{ - put("EFIRQ"); - settype(EXTFPUIRQLOG); -} - -bx_extfpuirq_c::~bx_extfpuirq_c(void) -{ - // nothing for now - BX_DEBUG(("Exit.")); -} - - - void -bx_extfpuirq_c::init(void) -{ - // called once when bochs initializes - DEV_register_iowrite_handler(this, write_handler, 0x00F0, "External FPU IRQ", 1); - DEV_register_irq(13, "External FPU IRQ"); -} - - void -bx_extfpuirq_c::reset(unsigned type) -{ - // We should handle IGNNE here - DEV_pic_lower_irq(13); -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_extfpuirq_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_EFI_SMF - bx_extfpuirq_c *class_ptr = (bx_extfpuirq_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - - void -bx_extfpuirq_c::write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_EFI_SMF - - // We should handle IGNNE here - DEV_pic_lower_irq(13); -} - diff --git a/tools/ioemu/iodev/extfpuirq.h b/tools/ioemu/iodev/extfpuirq.h deleted file mode 100644 index c32e71aa93..0000000000 --- a/tools/ioemu/iodev/extfpuirq.h +++ /dev/null @@ -1,51 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: extfpuirq.h,v 1.2 2003/01/07 08:17:15 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -#if BX_USE_EFI_SMF -# define BX_EXTFPUIRQ_SMF static -# define BX_EXTFPUIRQ_THIS theExternalFpuIrq-> -#else -# define BX_EXTFPUIRQ_SMF -# define BX_EXTFPUIRQ_THIS this-> -#endif - - -class bx_extfpuirq_c : public bx_devmodel_c { - -public: - bx_extfpuirq_c(void); - ~bx_extfpuirq_c(void); - virtual void init(void); - virtual void reset(unsigned type); - -private: - - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); -#if !BX_USE_EFI_SMF - void write(Bit32u address, Bit32u value, unsigned io_len); -#endif - }; diff --git a/tools/ioemu/iodev/floppy.cc b/tools/ioemu/iodev/floppy.cc deleted file mode 100644 index e4090d57b9..0000000000 --- a/tools/ioemu/iodev/floppy.cc +++ /dev/null @@ -1,1633 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: floppy.cc,v 1.69 2003/12/18 20:04:49 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -// -// Floppy Disk Controller Docs: -// Intel 82077A Data sheet -// ftp://void-core.2y.net/pub/docs/fdc/82077AA_FloppyControllerDatasheet.pdf -// Intel 82078 Data sheet -// ftp://download.intel.com/design/periphrl/datashts/29047403.PDF -// Other FDC references -// http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html -// And a port list: -// http://mudlist.eorbit.net/~adam/pickey/ports.html -// - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - - -extern "C" { -#include -} - -#ifdef __linux__ -extern "C" { -#include -#include -} -#endif -#include "bochs.h" -// windows.h included by bochs.h -#ifdef WIN32 -extern "C" { -#include -} -#endif -#define LOG_THIS theFloppyController-> - -bx_floppy_ctrl_c *theFloppyController; - -/* for main status register */ -#define FD_MS_MRQ 0x80 -#define FD_MS_DIO 0x40 -#define FD_MS_NDMA 0x20 -#define FD_MS_BUSY 0x10 -#define FD_MS_ACTD 0x08 -#define FD_MS_ACTC 0x04 -#define FD_MS_ACTB 0x02 -#define FD_MS_ACTA 0x01 - -#define FROM_FLOPPY 10 -#define TO_FLOPPY 11 - -#define FLOPPY_DMA_CHAN 2 - -typedef struct { - unsigned id; - Bit8u trk; - Bit8u hd; - Bit8u spt; - unsigned sectors; -} floppy_type_t; - -static floppy_type_t floppy_type[8] = { - {BX_FLOPPY_160K, 40, 1, 8, 320}, - {BX_FLOPPY_180K, 40, 1, 9, 360}, - {BX_FLOPPY_320K, 40, 2, 8, 640}, - {BX_FLOPPY_360K, 40, 2, 9, 720}, - {BX_FLOPPY_720K, 80, 2, 9, 1440}, - {BX_FLOPPY_1_2, 80, 2, 15, 2400}, - {BX_FLOPPY_1_44, 80, 2, 18, 2880}, - {BX_FLOPPY_2_88, 80, 2, 36, 5760} -}; - - - int -libfloppy_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - theFloppyController = new bx_floppy_ctrl_c (); - bx_devices.pluginFloppyDevice = theFloppyController; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theFloppyController, BX_PLUGIN_FLOPPY); - return(0); // Success -} - - void -libfloppy_LTX_plugin_fini(void) -{ -} - - -bx_floppy_ctrl_c::bx_floppy_ctrl_c(void) -{ - put("FDD"); - settype(FDLOG); - s.floppy_timer_index = BX_NULL_TIMER_HANDLE; -} - -bx_floppy_ctrl_c::~bx_floppy_ctrl_c(void) -{ - // nothing for now - BX_DEBUG(("Exit.")); -} - - - void -bx_floppy_ctrl_c::init(void) -{ - Bit8u i; - - BX_DEBUG(("Init $Id: floppy.cc,v 1.69 2003/12/18 20:04:49 vruppert Exp $")); - DEV_dma_register_8bit_channel(2, dma_read, dma_write, "Floppy Drive"); - DEV_register_irq(6, "Floppy Drive"); - for (unsigned addr=0x03F2; addr<=0x03F7; addr++) { - DEV_register_ioread_handler(this, read_handler, addr, "Floppy Drive", 1); - DEV_register_iowrite_handler(this, write_handler, addr, "Floppy Drive", 1); - } - - - DEV_cmos_set_reg(0x10, 0x00); /* start out with: no drive 0, no drive 1 */ - - BX_FD_THIS s.num_supported_floppies = 0; - - for (i=0; i<4; i++) { - BX_FD_THIS s.device_type[i] = BX_FLOPPY_NONE; - BX_FD_THIS s.media[i].type = BX_FLOPPY_NONE; - } - - // - // Floppy A setup - // - BX_FD_THIS s.media[0].sectors_per_track = 0; - BX_FD_THIS s.media[0].tracks = 0; - BX_FD_THIS s.media[0].heads = 0; - BX_FD_THIS s.media[0].sectors = 0; - BX_FD_THIS s.media[0].fd = -1; - BX_FD_THIS s.media_present[0] = 0; - BX_FD_THIS s.device_type[0] = bx_options.floppya.Odevtype->get (); - - switch (BX_FD_THIS s.device_type[0]) { - case BX_FLOPPY_NONE: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x00); - break; - case BX_FLOPPY_360K: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x10); - break; - case BX_FLOPPY_1_2: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x20); - break; - case BX_FLOPPY_720K: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x30); - break; - case BX_FLOPPY_1_44: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x40); - break; - case BX_FLOPPY_2_88: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x50); - break; - - // use CMOS reserved types - case BX_FLOPPY_160K: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x60); - BX_INFO(("WARNING: 1st floppy uses of reserved CMOS floppy drive type 6")); - break; - case BX_FLOPPY_180K: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x70); - BX_INFO(("WARNING: 1st floppy uses of reserved CMOS floppy drive type 7")); - break; - case BX_FLOPPY_320K: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x80); - BX_INFO(("WARNING: 1st floppy uses of reserved CMOS floppy drive type 8")); - break; - - default: - BX_PANIC(("unknown floppya type")); - } - if (BX_FD_THIS s.device_type[0] != BX_FLOPPY_NONE) - BX_FD_THIS s.num_supported_floppies++; - - if (bx_options.floppya.Otype->get () != BX_FLOPPY_NONE) { - if ( bx_options.floppya.Ostatus->get () == BX_INSERTED) { - if (evaluate_media(bx_options.floppya.Otype->get (), bx_options.floppya.Opath->getptr (), - & BX_FD_THIS s.media[0])) - BX_FD_THIS s.media_present[0] = 1; - else - bx_options.floppya.Ostatus->set(BX_EJECTED); -#define MED (BX_FD_THIS s.media[0]) - BX_INFO(("fd0: '%s' ro=%d, h=%d,t=%d,spt=%d", bx_options.floppya.Opath->getptr(), - MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track)); -#undef MED - } - } - - - // - // Floppy B setup - // - BX_FD_THIS s.media[1].sectors_per_track = 0; - BX_FD_THIS s.media[1].tracks = 0; - BX_FD_THIS s.media[1].heads = 0; - BX_FD_THIS s.media[1].sectors = 0; - BX_FD_THIS s.media[1].fd = -1; - BX_FD_THIS s.media_present[1] = 0; - BX_FD_THIS s.device_type[1] = bx_options.floppyb.Odevtype->get (); - - switch (BX_FD_THIS s.device_type[1]) { - case BX_FLOPPY_NONE: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x00); - break; - case BX_FLOPPY_360K: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x01); - break; - case BX_FLOPPY_1_2: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x02); - break; - case BX_FLOPPY_720K: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x03); - break; - case BX_FLOPPY_1_44: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x04); - break; - case BX_FLOPPY_2_88: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x05); - break; - - // use CMOS reserved types - case BX_FLOPPY_160K: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x06); - BX_INFO(("WARNING: 2nd floppy uses of reserved CMOS floppy drive type 6")); - break; - case BX_FLOPPY_180K: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x07); - BX_INFO(("WARNING: 2nd floppy uses of reserved CMOS floppy drive type 7")); - break; - case BX_FLOPPY_320K: - DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x08); - BX_INFO(("WARNING: 2nd floppy uses of reserved CMOS floppy drive type 8")); - break; - - default: - BX_PANIC(("unknown floppyb type")); - } - if (BX_FD_THIS s.device_type[1] != BX_FLOPPY_NONE) - BX_FD_THIS s.num_supported_floppies++; - - if (bx_options.floppyb.Otype->get () != BX_FLOPPY_NONE) { - if ( bx_options.floppyb.Ostatus->get () == BX_INSERTED) { - if (evaluate_media(bx_options.floppyb.Otype->get (), bx_options.floppyb.Opath->getptr (), - & BX_FD_THIS s.media[1])) - BX_FD_THIS s.media_present[1] = 1; - else - bx_options.floppyb.Ostatus->set(BX_EJECTED); -#define MED (BX_FD_THIS s.media[1]) - BX_INFO(("fd1: '%s' ro=%d, h=%d,t=%d,spt=%d", bx_options.floppyb.Opath->getptr(), - MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track)); -#undef MED - } - } - - - - /* CMOS Equipment Byte register */ - if (BX_FD_THIS s.num_supported_floppies > 0) { - DEV_cmos_set_reg(0x14, (DEV_cmos_get_reg(0x14) & 0x3e) | - ((BX_FD_THIS s.num_supported_floppies-1) << 6) | 1); - } - else - DEV_cmos_set_reg(0x14, (DEV_cmos_get_reg(0x14) & 0x3e)); - - - if (BX_FD_THIS s.floppy_timer_index == BX_NULL_TIMER_HANDLE) { - BX_FD_THIS s.floppy_timer_index = - bx_pc_system.register_timer( this, timer_handler, - bx_options.Ofloppy_command_delay->get (), 0,0, "floppy"); - } - - BX_DEBUG(("bx_options.Ofloppy_command_delay = %u", - (unsigned) bx_options.Ofloppy_command_delay->get ())); -} - - - - void -bx_floppy_ctrl_c::reset(unsigned type) -{ - Bit32u i; - - BX_FD_THIS s.pending_irq = 0; - BX_FD_THIS s.reset_sensei = 0; /* no reset result present */ - - BX_FD_THIS s.main_status_reg = 0; - BX_FD_THIS s.status_reg0 = 0; - BX_FD_THIS s.status_reg1 = 0; - BX_FD_THIS s.status_reg2 = 0; - BX_FD_THIS s.status_reg3 = 0; - - // software reset (via DOR port 0x3f2 bit 2) does not change DOR - if (type == BX_RESET_HARDWARE) { - BX_FD_THIS s.DOR = 0x0c; - // motor off, drive 3..0 - // DMA/INT enabled - // normal operation - // drive select 0 - - // DIR and CCR affected only by hard reset - for (i=0; i<4; i++) { - BX_FD_THIS s.DIR[i] |= 0x80; // disk changed - } - BX_FD_THIS s.data_rate = 0; /* 500 Kbps */ - } - - for (i=0; i<4; i++) { - BX_FD_THIS s.cylinder[i] = 0; - BX_FD_THIS s.head[i] = 0; - BX_FD_THIS s.sector[i] = 0; - } - - DEV_pic_lower_irq(6); - DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0); - enter_idle_phase(); -} - - - // static IO port read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_floppy_ctrl_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_FD_SMF - bx_floppy_ctrl_c *class_ptr = (bx_floppy_ctrl_c *) this_ptr; - - return( class_ptr->read(address, io_len) ); -} - - - /* reads from the floppy io ports */ - Bit32u -bx_floppy_ctrl_c::read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_FD_SMF - Bit8u status, value; - - if (bx_dbg.floppy) - BX_INFO(("read access to port %04x", (unsigned) address)); - - switch (address) { -#if BX_DMA_FLOPPY_IO - case 0x3F2: // diskette controller digital output register - value = BX_FD_THIS s.DOR; - return(value); - break; - - case 0x3F4: /* diskette controller main status register */ - status = BX_FD_THIS s.main_status_reg; - return(status); - break; - - case 0x3F5: /* diskette controller data */ - if (BX_FD_THIS s.result_size == 0) { - BX_ERROR(("port 0x3f5: no results to read")); - BX_FD_THIS s.main_status_reg = 0; - return BX_FD_THIS s.result[0]; - } - - value = BX_FD_THIS s.result[BX_FD_THIS s.result_index++]; - BX_FD_THIS s.main_status_reg &= 0xF0; - if (BX_FD_THIS s.result_index >= BX_FD_THIS s.result_size) { - if (!BX_FD_THIS s.reset_sensei) BX_FD_THIS s.pending_irq = 0; - DEV_pic_lower_irq(6); - enter_idle_phase(); - } - return(value); - break; -#endif // #if BX_DMA_FLOPPY_IO - - case 0x3F3: // Tape Drive Register - // see http://www.smsc.com/main/datasheets/37c93x.pdf page 18 for more details - - switch( BX_FD_THIS s.DOR & 0x03 ) - { - case 0x00: - if( (BX_FD_THIS s.DOR & 0x10) == 0) break; - return(2); - case 0x01: - if( (BX_FD_THIS s.DOR & 0x20) == 0) break; - return(1); - } - return(3); - - case 0x3F6: // Reserved for future floppy controllers - // This address shared with the hard drive controller - value = DEV_hd_read_handler(bx_devices.pluginHardDrive, address, io_len); - return( value ); - break; - - case 0x3F7: // diskette controller digital input register - // This address shared with the hard drive controller: - // Bit 7 : floppy - // Bits 6..0: hard drive - value = DEV_hd_read_handler(bx_devices.pluginHardDrive, address, io_len); - value &= 0x7f; - // add in diskette change line - value |= (BX_FD_THIS s.DIR[BX_FD_THIS s.DOR & 0x03] & 0x80); - return( value ); - break; - default: - BX_ERROR(("io_read: unsupported address 0x%04x", (unsigned) address)); - return(0); - break; - } -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_floppy_ctrl_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_FD_SMF - bx_floppy_ctrl_c *class_ptr = (bx_floppy_ctrl_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - - /* writes to the floppy io ports */ - void -bx_floppy_ctrl_c::write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_FD_SMF - Bit8u dma_and_interrupt_enable; - Bit8u normal_operation, prev_normal_operation; - Bit8u drive_select; - Bit8u motor_on_drive0, motor_on_drive1; - - if (bx_dbg.floppy) - BX_INFO(("write access to port %04x, value=%02x", - (unsigned) address, (unsigned) value)); - - switch (address) { -#if BX_DMA_FLOPPY_IO - case 0x3F2: /* diskette controller digital output register */ - motor_on_drive1 = value & 0x20; - motor_on_drive0 = value & 0x10; - dma_and_interrupt_enable = value & 0x08; - if (!dma_and_interrupt_enable) - BX_DEBUG(("DMA and interrupt capabilities disabled")); - normal_operation = value & 0x04; - drive_select = value & 0x03; - - prev_normal_operation = BX_FD_THIS s.DOR & 0x04; - BX_FD_THIS s.DOR = value; - - if (prev_normal_operation==0 && normal_operation) { - // transition from RESET to NORMAL - bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index, - bx_options.Ofloppy_command_delay->get (), 0 ); - } - else if (prev_normal_operation && normal_operation==0) { - // transition from NORMAL to RESET - BX_FD_THIS s.main_status_reg = FD_MS_BUSY; - BX_FD_THIS s.pending_command = 0xfe; // RESET pending - - } - BX_DEBUG(("io_write: digital output register")); - BX_DEBUG((" motor on, drive1 = %d", motor_on_drive1 > 0)); - BX_DEBUG((" motor on, drive0 = %d", motor_on_drive0 > 0)); - BX_DEBUG((" dma_and_interrupt_enable=%02x", - (unsigned) dma_and_interrupt_enable)); - BX_DEBUG((" normal_operation=%02x", - (unsigned) normal_operation)); - BX_DEBUG((" drive_select=%02x", - (unsigned) drive_select)); - if (BX_FD_THIS s.device_type[drive_select] == BX_FLOPPY_NONE) { - BX_DEBUG(("WARNING: not existing drive selected")); - } - break; - - case 0x3f4: /* diskette controller data rate select register */ - BX_ERROR(("io_write: data rate select register unsupported")); - break; - - case 0x3F5: /* diskette controller data */ - BX_DEBUG(("command = %02x", (unsigned) value)); - if (BX_FD_THIS s.command_complete) { - if (BX_FD_THIS s.pending_command!=0) - BX_PANIC(("io: 3f5: receiving new comm, old one (%02x) pending", - (unsigned) BX_FD_THIS s.pending_command)); - BX_FD_THIS s.command[0] = value; - BX_FD_THIS s.command_complete = 0; - BX_FD_THIS s.command_index = 1; - /* read/write command in progress */ - BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_BUSY; - switch (value) { - case 0x03: /* specify */ - BX_FD_THIS s.command_size = 3; - break; - case 0x04: // get status - BX_FD_THIS s.command_size = 2; - break; - case 0x07: /* recalibrate */ - BX_FD_THIS s.command_size = 2; - break; - case 0x08: /* sense interrupt status */ - BX_FD_THIS s.command_size = 1; - break; - case 0x0f: /* seek */ - BX_FD_THIS s.command_size = 3; - break; - case 0x4a: /* read ID */ - BX_FD_THIS s.command_size = 2; - break; - case 0x4d: /* format track */ - BX_FD_THIS s.command_size = 6; - break; - case 0x45: - case 0xc5: /* write normal data */ - BX_FD_THIS s.command_size = 9; - break; - case 0x46: - case 0x66: - case 0xc6: - case 0xe6: /* read normal data */ - BX_FD_THIS s.command_size = 9; - break; - - case 0x13: // Configure command (Enhanced) - BX_FD_THIS s.command_size = 4; - break; - - case 0x0e: // dump registers (Enhanced drives) - case 0x10: // Version command, standard controller returns 80h - case 0x18: // National Semiconductor version command; return 80h - // These commands are not implemented on the standard - // controller and return an error. They are available on - // the enhanced controller. - BX_DEBUG(("io_write: 0x3f5: unsupported floppy command 0x%02x", - (unsigned) value)); - BX_FD_THIS s.command_size = 0; // make sure we don't try to process this command - BX_FD_THIS s.status_reg0 = 0x80; // status: invalid command - enter_result_phase(); - break; - - default: - BX_ERROR(("io_write: 0x3f5: invalid floppy command 0x%02x", - (unsigned) value)); - BX_FD_THIS s.command_size = 0; // make sure we don't try to process this command - BX_FD_THIS s.status_reg0 = 0x80; // status: invalid command - enter_result_phase(); - break; - } - } - else { - BX_FD_THIS s.command[BX_FD_THIS s.command_index++] = - value; - } - if (BX_FD_THIS s.command_index == - BX_FD_THIS s.command_size) { - /* read/write command not in progress any more */ - floppy_command(); - BX_FD_THIS s.command_complete = 1; - } - BX_DEBUG(("io_write: diskette controller data")); - return; - break; -#endif // #if BX_DMA_FLOPPY_IO - - case 0x3F6: /* diskette controller (reserved) */ - BX_DEBUG(("io_write: reserved register 0x3f6 unsupported")); - // this address shared with the hard drive controller - DEV_hd_write_handler(bx_devices.pluginHardDrive, address, value, io_len); - break; - -#if BX_DMA_FLOPPY_IO - case 0x3F7: /* diskette controller configuration control register */ - BX_DEBUG(("io_write: config control register")); - BX_FD_THIS s.data_rate = value & 0x03; - switch (BX_FD_THIS s.data_rate) { - case 0: BX_DEBUG((" 500 Kbps")); break; - case 1: BX_DEBUG((" 300 Kbps")); break; - case 2: BX_DEBUG((" 250 Kbps")); break; - case 3: BX_DEBUG((" 1 Mbps")); break; - } - return; - break; - - default: - BX_ERROR(("io_write ignored: 0x%04x = 0x%02x", (unsigned) address, (unsigned) value)); - break; -#endif // #if BX_DMA_FLOPPY_IO - } -} - - - - void -bx_floppy_ctrl_c::floppy_command(void) -{ -#if BX_PROVIDE_CPU_MEMORY==0 - BX_PANIC(("floppy_command(): uses DMA: not supported for" - " external environment")); -#else - unsigned i; - Bit8u step_rate_time; - Bit8u head_unload_time; - Bit8u head_load_time; - Bit8u motor_on; - Bit8u head, drive, cylinder, sector, eot; - Bit8u sector_size, data_length; - Bit32u logical_sector; - - - BX_DEBUG(("FLOPPY COMMAND: ")); - for (i=0; i> 4; - head_unload_time = BX_FD_THIS s.command[1] & 0x0f; - head_load_time = BX_FD_THIS s.command[2] >> 1; - if (BX_FD_THIS s.command[2] & 0x01) - BX_ERROR(("non DMA mode selected")); - enter_idle_phase(); - return; - break; - - case 0x04: // get status - drive = (BX_FD_THIS s.command[1] & 0x03); - BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01; - BX_FD_THIS s.status_reg3 = 0x28 | (BX_FD_THIS s.head[drive]<<2) | drive - | (BX_FD_THIS s.media[drive].write_protected ? 0x40 : 0x00); - if (BX_FD_THIS s.cylinder[drive] == 0) BX_FD_THIS s.status_reg3 |= 0x10; - enter_result_phase(); - return; - break; - - case 0x07: // recalibrate - drive = (BX_FD_THIS s.command[1] & 0x03); - BX_FD_THIS s.DOR &= 0xfc; - BX_FD_THIS s.DOR |= drive; - BX_DEBUG(("floppy_command(): recalibrate drive %u", - (unsigned) drive)); - motor_on = ( (BX_FD_THIS s.DOR>>(drive+4)) - & 0x01 ); - if (motor_on == 0) { - BX_INFO(("floppy_command(): recal drive with motor off")); - } - if (drive==0) - BX_FD_THIS s.DOR |= 0x10; // turn on MOTA - else - BX_FD_THIS s.DOR |= 0x20; // turn on MOTB - bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index, - bx_options.Ofloppy_command_delay->get (), 0 ); - /* command head to track 0 - * controller set to non-busy - * error condition noted in Status reg 0's equipment check bit - * seek end bit set to 1 in Status reg 0 regardless of outcome - * The last two are taken care of in timer(). - */ - BX_FD_THIS s.cylinder[drive] = 0; - BX_FD_THIS s.main_status_reg = (1 << drive); - return; - break; - - case 0x08: /* sense interrupt status */ - /* execution: - * get status - * result: - * no interupt - * byte0 = status reg0 - * byte1 = current cylinder number (0 to 79) - */ - drive = BX_FD_THIS s.DOR & 0x03; - if (!BX_FD_THIS s.pending_irq) { - BX_FD_THIS s.status_reg0 = 0x80; - } - else { - if (BX_FD_THIS s.reset_sensei > 0) { - drive = 4 - BX_FD_THIS s.reset_sensei; - BX_FD_THIS s.status_reg0 &= 0xf8; - BX_FD_THIS s.status_reg0 |= (BX_FD_THIS s.head[drive] << 2) | drive; - BX_FD_THIS s.reset_sensei--; - } - } - - BX_DEBUG(("sense interrupt status")); - enter_result_phase(); - return; - break; - - case 0x0f: /* seek */ - /* command: - * byte0 = 0F - * byte1 = drive & head select - * byte2 = cylinder number - * execution: - * postion head over specified cylinder - * result: - * no result bytes, issues an interrupt - */ - drive = BX_FD_THIS s.command[1] & 0x03; - BX_FD_THIS s.DOR &= 0xfc; - BX_FD_THIS s.DOR |= drive; - - BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01; - BX_FD_THIS s.cylinder[drive] = BX_FD_THIS s.command[2]; - /* ??? should also check cylinder validity */ - bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index, - bx_options.Ofloppy_command_delay->get (), 0 ); - /* data reg not ready, drive busy */ - BX_FD_THIS s.main_status_reg = (1 << drive); - return; - break; - - case 0x13: // Configure - BX_DEBUG(("configure (eis = 0x%02x)", BX_FD_THIS s.command[2] & 0x40 )); - BX_DEBUG(("configure (efifo = 0x%02x)", BX_FD_THIS s.command[2] & 0x20 )); - BX_DEBUG(("configure (no poll = 0x%02x)", BX_FD_THIS s.command[2] & 0x10 )); - BX_DEBUG(("configure (fifothr = 0x%02x)", BX_FD_THIS s.command[2] & 0x0f )); - BX_DEBUG(("configure (pretrk = 0x%02x)", BX_FD_THIS s.command[3] )); - enter_idle_phase(); - return; - break; - - case 0x4a: // read ID - drive = BX_FD_THIS s.command[1] & 0x03; - BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01; - BX_FD_THIS s.DOR &= 0xfc; - BX_FD_THIS s.DOR |= drive; - - motor_on = (BX_FD_THIS s.DOR>>(drive+4)) & 0x01; - if (motor_on == 0) { - BX_ERROR(("floppy_command(): 0x4a: motor not on")); - BX_FD_THIS s.main_status_reg = FD_MS_BUSY; - return; - } - if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE) - BX_PANIC(("floppy_command(): read ID: bad drive #%d", drive)); - BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive]<<2) | drive; - bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index, - bx_options.Ofloppy_command_delay->get (), 0 ); - /* data reg not ready, controller busy */ - BX_FD_THIS s.main_status_reg = FD_MS_BUSY; - return; - break; - - case 0x4d: // format track - drive = BX_FD_THIS s.command[1] & 0x03; - BX_FD_THIS s.DOR &= 0xfc; - BX_FD_THIS s.DOR |= drive; - - motor_on = (BX_FD_THIS s.DOR>>(drive+4)) & 0x01; - if (motor_on == 0) - BX_PANIC(("floppy_command(): format track: motor not on")); - BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01; - sector_size = BX_FD_THIS s.command[2]; - BX_FD_THIS s.format_count = BX_FD_THIS s.command[3]; - BX_FD_THIS s.format_fillbyte = BX_FD_THIS s.command[5]; - if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE) - BX_PANIC(("floppy_command(): format track: bad drive #%d", drive)); - - if (sector_size != 0x02) { // 512 bytes - BX_PANIC(("format track: sector size %d not supported", 128<> 7); - if ( (BX_FD_THIS s.DOR & 0x08) == 0 ) - BX_PANIC(("read/write command with DMA and int disabled")); - drive = BX_FD_THIS s.command[1] & 0x03; - BX_FD_THIS s.DOR &= 0xfc; - BX_FD_THIS s.DOR |= drive; - - motor_on = (BX_FD_THIS s.DOR>>(drive+4)) & 0x01; - if (motor_on == 0) - BX_PANIC(("floppy_command(): read/write: motor not on")); - head = BX_FD_THIS s.command[3] & 0x01; - cylinder = BX_FD_THIS s.command[2]; /* 0..79 depending */ - sector = BX_FD_THIS s.command[4]; /* 1..36 depending */ - eot = BX_FD_THIS s.command[6]; /* 1..36 depending */ - sector_size = BX_FD_THIS s.command[5]; - data_length = BX_FD_THIS s.command[8]; - BX_DEBUG(("read/write normal data")); - BX_DEBUG(("BEFORE")); - BX_DEBUG((" drive = %u", (unsigned) drive)); - BX_DEBUG((" head = %u", (unsigned) head)); - BX_DEBUG((" cylinder = %u", (unsigned) cylinder)); - BX_DEBUG((" sector = %u", (unsigned) sector)); - BX_DEBUG((" eot = %u", (unsigned) eot)); - if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE) - BX_PANIC(("floppy_command(): read/write: bad drive #%d", drive)); - - // check that head number in command[1] bit two matches the head - // reported in the head number field. Real floppy drives are - // picky about this, as reported in SF bug #439945, (Floppy drive - // read input error checking). - if (head != ((BX_FD_THIS s.command[1]>>2)&1)) { - BX_ERROR(("head number in command[1] doesn't match head field")); - BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; // abnormal termination - BX_FD_THIS s.status_reg1 = 0x04; // 0000 0100 - BX_FD_THIS s.status_reg2 = 0x00; // 0000 0000 - enter_result_phase(); - return; - } - - if ( BX_FD_THIS s.media_present[drive] == 0 ) { - // media not in drive, return error - - BX_INFO(("attempt to read/write sector %u," - " sectors/track=%u with media not present", - (unsigned) sector, - (unsigned) BX_FD_THIS s.media[drive].sectors_per_track)); - BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; // abnormal termination - BX_FD_THIS s.status_reg1 = 0x25; // 0010 0101 - BX_FD_THIS s.status_reg2 = 0x31; // 0011 0001 - enter_result_phase(); - return; - } - - if (sector_size != 0x02) { // 512 bytes - BX_PANIC(("read/write command: sector size %d not supported", 128<= BX_FD_THIS s.media[drive].tracks ) { - BX_PANIC(("io: norm r/w parms out of range: sec#%02xh cyl#%02xh eot#%02xh head#%02xh", - (unsigned) sector, (unsigned) cylinder, (unsigned) eot, - (unsigned) head)); - return; - } - - if (sector > BX_FD_THIS s.media[drive].sectors_per_track) { - // requested sector > last sector on track - BX_INFO(("attempt to read/write sector %u," - " sectors/track=%u", (unsigned) sector, - (unsigned) BX_FD_THIS s.media[drive].sectors_per_track)); - // set controller to where drive would have left off - // after it discovered the sector was past EOT - BX_FD_THIS s.cylinder[drive] = cylinder; - BX_FD_THIS s.head[drive] = head; - BX_FD_THIS s.sector[drive] = BX_FD_THIS s.media[drive].sectors_per_track; - - // 0100 0HDD abnormal termination - BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; - // 1000 0101 end of cyl/NDAT/NID - BX_FD_THIS s.status_reg1 = 0x85; - // 0000 0000 - BX_FD_THIS s.status_reg2 = 0x00; - enter_result_phase(); - return; - } - - if (cylinder != BX_FD_THIS s.cylinder[drive]) - BX_DEBUG(("io: cylinder request != current cylinder")); - - // original assumed all floppies had two sides...now it does not *delete this comment line* - logical_sector = (cylinder * BX_FD_THIS s.media[drive].heads * BX_FD_THIS s.media[drive].sectors_per_track) + - (head * BX_FD_THIS s.media[drive].sectors_per_track) + - (sector - 1); - - if (logical_sector >= BX_FD_THIS s.media[drive].sectors) { - BX_PANIC(("io: logical sector out of bounds")); - } - - BX_FD_THIS s.cylinder[drive] = cylinder; - BX_FD_THIS s.sector[drive] = sector; - BX_FD_THIS s.head[drive] = head; - - if ((BX_FD_THIS s.command[0] & 0x4f) == 0x46) { // read - floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer, - 512, FROM_FLOPPY); - - DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1); - - /* data reg not ready, controller busy */ - BX_FD_THIS s.main_status_reg = FD_MS_BUSY; - return; - } - else if ((BX_FD_THIS s.command[0] & 0x7f) == 0x45) { // write - - DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1); - - /* data reg not ready, controller busy */ - BX_FD_THIS s.main_status_reg = FD_MS_BUSY; - return; - } - else - BX_PANIC(("floppy_command(): unknown read/write command")); - - return; - break; - - default: // invalid or unsupported command; these are captured in write() above - BX_PANIC(("You should never get here! cmd = 0x%02x", - BX_FD_THIS s.command[0])); - } -#endif -} - - void -bx_floppy_ctrl_c::floppy_xfer(Bit8u drive, Bit32u offset, Bit8u *buffer, - Bit32u bytes, Bit8u direction) -{ - int ret; - - if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE) - BX_PANIC(("floppy_xfer: bad drive #%d", drive)); - - if (bx_dbg.floppy) { - BX_INFO(("drive=%u", (unsigned) drive)); - BX_INFO(("offset=%u", (unsigned) offset)); - BX_INFO(("bytes=%u", (unsigned) bytes)); - BX_INFO(("direction=%s", (direction==FROM_FLOPPY)? "from" : "to")); - } - -#if BX_WITH_MACOS - if (strcmp(bx_options.floppya.Opath->getptr (), SuperDrive)) -#endif - { - ret = lseek(BX_FD_THIS s.media[drive].fd, offset, SEEK_SET); - if (ret < 0) { - BX_PANIC(("could not perform lseek() on floppy image file")); - } - } - - if (direction == FROM_FLOPPY) { -#if BX_WITH_MACOS - if (!strcmp(bx_options.floppya.Opath->getptr (), SuperDrive)) - ret = fd_read((char *) buffer, offset, bytes); - else -#endif - ret = ::read(BX_FD_THIS s.media[drive].fd, (bx_ptr_t) buffer, bytes); - if (ret < int(bytes)) { - /* ??? */ - if (ret > 0) { - BX_INFO(("partial read() on floppy image returns %u/%u", - (unsigned) ret, (unsigned) bytes)); - memset(buffer + ret, 0, bytes - ret); - } - else { - BX_INFO(("read() on floppy image returns 0")); - memset(buffer, 0, bytes); - } - } - } - - else { // TO_FLOPPY - BX_ASSERT (!BX_FD_THIS s.media[drive].write_protected); -#if BX_WITH_MACOS - if (!strcmp(bx_options.floppya.Opath->getptr (), SuperDrive)) - ret = fd_write((char *) buffer, offset, bytes); - else -#endif - ret = ::write(BX_FD_THIS s.media[drive].fd, (bx_ptr_t) buffer, bytes); - if (ret < int(bytes)) { - BX_PANIC(("could not perform write() on floppy image file")); - } - } -} - - - - void -bx_floppy_ctrl_c::timer_handler(void *this_ptr) -{ - - bx_floppy_ctrl_c *class_ptr = (bx_floppy_ctrl_c *) this_ptr; - - class_ptr->timer(); -} - - void -bx_floppy_ctrl_c::timer() -{ - Bit8u drive; - - drive = BX_FD_THIS s.DOR & 0x03; - switch ( BX_FD_THIS s.pending_command ) { - case 0x07: // recal - case 0x0f: // seek - BX_FD_THIS s.status_reg0 = 0x20 | (BX_FD_THIS s.head[drive]<<2) | drive; - if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE) { - BX_FD_THIS s.status_reg0 |= 0x50; - } - else if (BX_FD_THIS s.media_present[drive] == 0) { - BX_FD_THIS s.status_reg0 |= 0x40; - BX_FD_THIS s.status_reg1 = 0x25; - BX_FD_THIS s.status_reg2 = 0x31; - } - - /* reset changeline */ - if (drive > 1) return; - if (BX_FD_THIS s.media_present[drive]) - BX_FD_THIS s.DIR[drive] &= ~0x80; // clear disk change line - - enter_idle_phase(); - raise_interrupt(); - break; - - case 0x4a: /* read ID */ - enter_result_phase(); - break; - - case 0xfe: // (contrived) RESET - theFloppyController->reset(BX_RESET_SOFTWARE); - BX_FD_THIS s.pending_command = 0; - BX_FD_THIS s.status_reg0 = 0xc0; - raise_interrupt(); - BX_FD_THIS s.reset_sensei = 4; - break; - - case 0x00: // nothing pending? - break; - - default: - BX_PANIC(("floppy:timer(): unknown case %02x", - (unsigned) BX_FD_THIS s.pending_command)); - } - return; -} - - void -bx_floppy_ctrl_c::dma_write(Bit8u *data_byte) -{ - // A DMA write is from I/O to Memory - // We need to return then next data byte from the floppy buffer - // to be transfered via the DMA to memory. (read block from floppy) - - - *data_byte = BX_FD_THIS s.floppy_buffer[BX_FD_THIS s.floppy_buffer_index++]; - - if (BX_FD_THIS s.floppy_buffer_index >= 512) { - Bit8u drive; - - drive = BX_FD_THIS s.DOR & 0x03; - increment_sector(); // increment to next sector before retrieving next one - BX_FD_THIS s.floppy_buffer_index = 0; - if (DEV_dma_get_tc()) { // Terminal Count line, done - BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive] << 2) | drive; - BX_FD_THIS s.status_reg1 = 0; - BX_FD_THIS s.status_reg2 = 0; - - if (bx_dbg.floppy) { - BX_INFO(("<>")); - BX_INFO(("AFTER")); - BX_INFO((" drive = %u", (unsigned) drive)); - BX_INFO((" head = %u", (unsigned) BX_FD_THIS s.head[drive])); - BX_INFO((" cylinder = %u", (unsigned) BX_FD_THIS s.cylinder[drive])); - BX_INFO((" sector = %u", (unsigned) BX_FD_THIS s.sector[drive])); - } - - DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0); - enter_result_phase(); - } - else { // more data to transfer - Bit32u logical_sector; - - // original assumed all floppies had two sides...now it does not *delete this comment line* - logical_sector = (BX_FD_THIS s.cylinder[drive] * BX_FD_THIS s.media[drive].heads * - BX_FD_THIS s.media[drive].sectors_per_track) + - (BX_FD_THIS s.head[drive] * - BX_FD_THIS s.media[drive].sectors_per_track) + - (BX_FD_THIS s.sector[drive] - 1); - - floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer, - 512, FROM_FLOPPY); - } - } -} - - void -bx_floppy_ctrl_c::dma_read(Bit8u *data_byte) -{ - // A DMA read is from Memory to I/O - // We need to write the data_byte which was already transfered from memory - // via DMA to I/O (write block to floppy) - - Bit8u drive; - Bit32u logical_sector; - - drive = BX_FD_THIS s.DOR & 0x03; - if (BX_FD_THIS s.pending_command == 0x4d) { // format track in progress - --BX_FD_THIS s.format_count; - switch (3 - (BX_FD_THIS s.format_count & 0x03)) { - case 0: - BX_FD_THIS s.cylinder[drive] = *data_byte; - break; - case 1: - if (*data_byte != BX_FD_THIS s.head[drive]) - BX_ERROR(("head number does not match head field")); - break; - case 2: - BX_FD_THIS s.sector[drive] = *data_byte; - break; - case 3: - if (*data_byte != 2) BX_ERROR(("dma_read: sector size %d not supported", 128<<(*data_byte))); - BX_DEBUG(("formatting cylinder %u head %u sector %u", - BX_FD_THIS s.cylinder[drive], BX_FD_THIS s.head[drive], - BX_FD_THIS s.sector[drive])); - for (unsigned i = 0; i < 512; i++) { - BX_FD_THIS s.floppy_buffer[i] = BX_FD_THIS s.format_fillbyte; - } - // original assumed all floppies had two sides...now it does not *delete this comment line* - logical_sector = (BX_FD_THIS s.cylinder[drive] * BX_FD_THIS s.media[drive].heads * BX_FD_THIS s.media[drive].sectors_per_track) + - (BX_FD_THIS s.head[drive] * BX_FD_THIS s.media[drive].sectors_per_track) + - (BX_FD_THIS s.sector[drive] - 1); - floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer, - 512, TO_FLOPPY); - break; - } - if ((BX_FD_THIS s.format_count == 0) || (DEV_dma_get_tc())) { - BX_FD_THIS s.format_count = 0; - BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive] << 2) | drive; - DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0); - enter_result_phase(); - } - return; - } - - BX_FD_THIS s.floppy_buffer[BX_FD_THIS s.floppy_buffer_index++] = *data_byte; - - if (BX_FD_THIS s.floppy_buffer_index >= 512) { - // original assumed all floppies had two sides...now it does not *delete this comment line* - logical_sector = (BX_FD_THIS s.cylinder[drive] * BX_FD_THIS s.media[drive].heads * BX_FD_THIS s.media[drive].sectors_per_track) + - (BX_FD_THIS s.head[drive] * BX_FD_THIS s.media[drive].sectors_per_track) + - (BX_FD_THIS s.sector[drive] - 1); - if ( BX_FD_THIS s.media[drive].write_protected ) { - // write protected error - BX_INFO(("tried to write disk %u, which is write-protected", drive)); - // ST0: IC1,0=01 (abnormal termination: started execution but failed) - BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; - // ST1: DataError=1, NDAT=1, NotWritable=1, NID=1 - BX_FD_THIS s.status_reg1 = 0x27; // 0010 0111 - // ST2: CRCE=1, SERR=1, BCYL=1, NDAM=1. - BX_FD_THIS s.status_reg2 = 0x31; // 0011 0001 - enter_result_phase(); - return; - } - floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer, - 512, TO_FLOPPY); - increment_sector(); // increment to next sector after writing current one - BX_FD_THIS s.floppy_buffer_index = 0; - if (DEV_dma_get_tc()) { // Terminal Count line, done - BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive] << 2) | drive; - BX_FD_THIS s.status_reg1 = 0; - BX_FD_THIS s.status_reg2 = 0; - - if (bx_dbg.floppy) { - BX_INFO(("<>")); - BX_INFO(("AFTER")); - BX_INFO((" drive = %u", (unsigned) drive)); - BX_INFO((" head = %u", (unsigned) BX_FD_THIS s.head[drive])); - BX_INFO((" cylinder = %u", (unsigned) BX_FD_THIS s.cylinder[drive])); - BX_INFO((" sector = %u", (unsigned) BX_FD_THIS s.sector[drive])); - } - - DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0); - enter_result_phase(); - } - else { // more data to transfer - } // else - } // if BX_FD_THIS s.floppy_buffer_index >= 512 -} - - void -bx_floppy_ctrl_c::raise_interrupt(void) -{ - DEV_pic_raise_irq(6); - BX_FD_THIS s.pending_irq = 1; - BX_FD_THIS s.reset_sensei = 0; -} - - - void -bx_floppy_ctrl_c::increment_sector(void) -{ - Bit8u drive; - - drive = BX_FD_THIS s.DOR & 0x03; - - // values after completion of data xfer - // ??? calculation depends on base_count being multiple of 512 - BX_FD_THIS s.sector[drive] ++; - if (BX_FD_THIS s.sector[drive] > BX_FD_THIS s.media[drive].sectors_per_track) { - BX_FD_THIS s.sector[drive] = 1; - if (BX_FD_THIS s.multi_track) { - BX_FD_THIS s.head[drive] ++; - if (BX_FD_THIS s.head[drive] > 1) { - BX_FD_THIS s.head[drive] = 0; - BX_FD_THIS s.cylinder[drive] ++; - } - } - else { - BX_FD_THIS s.cylinder[drive] ++; - } - if (BX_FD_THIS s.cylinder[drive] >= BX_FD_THIS s.media[drive].tracks) { - // Set to 1 past last possible cylinder value. - // I notice if I set it to tracks-1, prama linux won't boot. - BX_FD_THIS s.cylinder[drive] = BX_FD_THIS s.media[drive].tracks; - BX_INFO(("increment_sector: clamping cylinder to max")); - } - } -} - - unsigned -bx_floppy_ctrl_c::set_media_status(unsigned drive, unsigned status) -{ - char *path; - unsigned type; - - if (drive == 0) - type = bx_options.floppya.Otype->get (); - else - type = bx_options.floppyb.Otype->get (); - - // if setting to the current value, nothing to do - if ((status == BX_FD_THIS s.media_present[drive]) && - ((status == 0) || (type == BX_FD_THIS s.media[drive].type))) - return(status); - - if (status == 0) { - // eject floppy - if (BX_FD_THIS s.media[drive].fd >= 0) { - close( BX_FD_THIS s.media[drive].fd ); - BX_FD_THIS s.media[drive].fd = -1; - } - BX_FD_THIS s.media_present[drive] = 0; - if (drive == 0) { - bx_options.floppya.Ostatus->set(BX_EJECTED); - } else { - bx_options.floppyb.Ostatus->set(BX_EJECTED); - } - BX_FD_THIS s.DIR[drive] |= 0x80; // disk changed line - return(0); - } - else { - // insert floppy - if (drive == 0) { - path = bx_options.floppya.Opath->getptr (); - } - else { - path = bx_options.floppyb.Opath->getptr (); - } - if (!strcmp(path, "none")) - return(0); - if (evaluate_media(type, path, & BX_FD_THIS s.media[drive])) { - BX_FD_THIS s.media_present[drive] = 1; - if (drive == 0) { -#define MED (BX_FD_THIS s.media[0]) - BX_INFO(("fd0: '%s' ro=%d, h=%d,t=%d,spt=%d", bx_options.floppya.Opath->getptr(), - MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track)); -#undef MED - bx_options.floppya.Ostatus->set(BX_INSERTED); - } else { -#define MED (BX_FD_THIS s.media[1]) - BX_INFO(("fd1: '%s' ro=%d, h=%d,t=%d,spt=%d", bx_options.floppyb.Opath->getptr(), - MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track)); -#undef MED - bx_options.floppyb.Ostatus->set(BX_INSERTED); - } - BX_FD_THIS s.DIR[drive] |= 0x80; // disk changed line - return(1); - } - else { - BX_FD_THIS s.media_present[drive] = 0; - if (drive == 0) { - bx_options.floppya.Ostatus->set(BX_EJECTED); - } else { - bx_options.floppyb.Ostatus->set(BX_EJECTED); - } - return(0); - } - } -} - - unsigned -bx_floppy_ctrl_c::get_media_status(unsigned drive) -{ - return( BX_FD_THIS s.media_present[drive] ); -} - -#ifdef O_BINARY -#define BX_RDONLY O_RDONLY | O_BINARY -#define BX_RDWR O_RDWR | O_BINARY -#else -#define BX_RDONLY O_RDONLY -#define BX_RDWR O_RDWR -#endif - - bx_bool -bx_floppy_ctrl_c::evaluate_media(unsigned type, char *path, floppy_t *media) -{ - struct stat stat_buf; - int i, ret; - int idx = -1; -#ifdef __linux__ - struct floppy_struct floppy_geom; -#endif -#ifdef WIN32 - char sTemp[1024]; - bx_bool raw_floppy = 0; - HANDLE hFile; - DWORD bytes; - DISK_GEOMETRY dg; - unsigned tracks, heads, spt; -#endif - - if (type == BX_FLOPPY_NONE) - return(0); - - //If media file is already open, close it before reopening. - if(media->fd >=0) { - close(media->fd); - media->fd=-1; - } - - // open media file (image file or device) - media->write_protected = 0; -#ifdef macintosh - media->fd = 0; - if (strcmp(bx_options.floppya.Opath->getptr (), SuperDrive)) -#endif -#ifdef WIN32 - if ( (isalpha(path[0])) && (path[1] == ':') && (strlen(path) == 2) ) { - raw_floppy = 1; - wsprintf(sTemp, "\\\\.\\%s", path); - hFile = CreateFile(sTemp, GENERIC_READ, FILE_SHARE_WRITE, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) { - BX_ERROR(("Cannot open floppy drive")); - return(0); - } else { - if (!DeviceIoControl(hFile, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &dg, sizeof(dg), &bytes, NULL)) { - BX_ERROR(("No media in floppy drive")); - CloseHandle(hFile); - return(0); - } else { - tracks = (unsigned)dg.Cylinders.QuadPart; - heads = (unsigned)dg.TracksPerCylinder; - spt = (unsigned)dg.SectorsPerTrack; - } - CloseHandle(hFile); - } - media->fd = open(sTemp, BX_RDWR); - } else { - media->fd = open(path, BX_RDWR); - } -#else - media->fd = open(path, BX_RDWR); -#endif - - if (media->fd < 0) { - BX_INFO(( "tried to open '%s' read/write: %s",path,strerror(errno) )); - // try opening the file read-only - media->write_protected = 1; -#ifdef macintosh - media->fd = 0; - if (strcmp(bx_options.floppya.Opath->getptr (), SuperDrive)) -#endif -#ifdef WIN32 - if (raw_floppy == 1) { - media->fd = open(sTemp, BX_RDONLY); - } else { - media->fd = open(path, BX_RDONLY); - } -#else - media->fd = open(path, BX_RDONLY); -#endif - if (media->fd < 0) { - // failed to open read-only too - BX_INFO(( "tried to open '%s' read only: %s",path,strerror(errno) )); - media->type = type; - return(0); - } - } - -#if BX_WITH_MACOS - if (!strcmp(bx_options.floppya.Opath->getptr (), SuperDrive)) - ret = fd_stat(&stat_buf); - else - ret = fstat(media->fd, &stat_buf); -#elif defined(WIN32) - if (raw_floppy) { - memset (&stat_buf, 0, sizeof(stat_buf)); - stat_buf.st_mode = S_IFCHR; - ret = 0; - } else { - ret = fstat(media->fd, &stat_buf); - } -#else - // unix - ret = fstat(media->fd, &stat_buf); -#endif - if (ret) { - BX_PANIC(("fstat floppy 0 drive image file returns error: %s", strerror(errno))); - return(0); - } - - for (i = 0; i < 8; i++) { - if (type == floppy_type[i].id) idx = i; - } - if (idx == -1 ) { - BX_PANIC(("evaluate_media: unknown media type")); - return(0); - } - if ( S_ISREG(stat_buf.st_mode) ) { - // regular file - switch (type) { - // use CMOS reserved types - case BX_FLOPPY_160K: // 160K 5.25" - case BX_FLOPPY_180K: // 180K 5.25" - case BX_FLOPPY_320K: // 320K 5.25" - // standard floppy types - case BX_FLOPPY_360K: // 360K 5.25" - case BX_FLOPPY_720K: // 720K 3.5" - case BX_FLOPPY_1_2: // 1.2M 5.25" - case BX_FLOPPY_2_88: // 2.88M 3.5" - media->type = type; - media->tracks = floppy_type[idx].trk; - media->heads = floppy_type[idx].hd; - media->sectors_per_track = floppy_type[idx].spt; - media->sectors = floppy_type[idx].sectors; - if (stat_buf.st_size > (media->sectors * 512)) { - BX_INFO(("evaluate_media: size of file '%s' (%lu) too large for selected type", - path, (unsigned long) stat_buf.st_size)); - return(0); - } - break; - default: // 1.44M 3.5" - media->type = type; - if (stat_buf.st_size <= 1474560) { - media->tracks = floppy_type[idx].trk; - media->heads = floppy_type[idx].hd; - media->sectors_per_track = floppy_type[idx].spt; - } - else if (stat_buf.st_size == 1720320) { - media->sectors_per_track = 21; - media->tracks = 80; - media->heads = 2; - } - else if (stat_buf.st_size == 1763328) { - media->sectors_per_track = 21; - media->tracks = 82; - media->heads = 2; - } - else { - BX_INFO(("evaluate_media: file '%s' of unknown size %lu", - path, (unsigned long) stat_buf.st_size)); - return(0); - } - media->sectors = media->heads * media->tracks * media->sectors_per_track; - } - return(1); // success - } - - else if ( S_ISCHR(stat_buf.st_mode) -#if BX_WITH_MACOS == 0 -#ifdef S_ISBLK - || S_ISBLK(stat_buf.st_mode) -#endif -#endif - ) { - // character or block device - // assume media is formatted to typical geometry for drive - media->type = type; -#ifdef __linux__ - if (ioctl(media->fd, FDGETPRM, &floppy_geom) < 0) { - BX_ERROR(("cannot determine media geometry")); - return(0); - } - media->tracks = floppy_geom.track; - media->heads = floppy_geom.head; - media->sectors_per_track = floppy_geom.sect; - media->sectors = floppy_geom.size; -#elif defined(WIN32) - media->tracks = tracks; - media->heads = heads; - media->sectors_per_track = spt; - media->sectors = media->heads * media->tracks * media->sectors_per_track; -#else - media->tracks = floppy_type[idx].trk; - media->heads = floppy_type[idx].hd; - media->sectors_per_track = floppy_type[idx].spt; - media->sectors = floppy_type[idx].sectors; -#endif - return(1); // success - } - else { - // unknown file type - BX_INFO(("unknown mode type")); - return(0); - } -} - - -void -bx_floppy_ctrl_c::enter_result_phase(void) -{ - - Bit8u drive; - - drive = BX_FD_THIS s.DOR & 0x03; - - /* these are always the same */ - BX_FD_THIS s.result_index = 0; - BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY; - - /* invalid command */ - if ((BX_FD_THIS s.status_reg0 & 0xc0) == 0x80) { - BX_FD_THIS s.result_size = 1; - BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0; - return; - } - - switch (BX_FD_THIS s.pending_command) { - case 0x04: // get status - BX_FD_THIS s.result_size = 1; - BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg3; - break; - case 0x08: // sense interrupt - BX_FD_THIS s.result_size = 2; - BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0; - BX_FD_THIS s.result[1] = BX_FD_THIS s.cylinder[drive]; - break; - case 0x4a: // read ID - case 0x4d: // format track - case 0x46: // read normal data - case 0x66: - case 0xc6: - case 0xe6: - case 0x45: // write normal data - case 0xc5: - BX_FD_THIS s.result_size = 7; - BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0; - BX_FD_THIS s.result[1] = BX_FD_THIS s.status_reg1; - BX_FD_THIS s.result[2] = BX_FD_THIS s.status_reg2; - BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive]; - BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive]; - BX_FD_THIS s.result[5] = BX_FD_THIS s.sector[drive]; - BX_FD_THIS s.result[6] = 2; /* sector size code */ - raise_interrupt(); - break; - } -} - -void -bx_floppy_ctrl_c::enter_idle_phase(void) -{ - BX_FD_THIS s.main_status_reg &= 0x0f; // leave drive status untouched - BX_FD_THIS s.main_status_reg |= FD_MS_MRQ; // data register ready - - BX_FD_THIS s.command_complete = 1; /* waiting for new command */ - BX_FD_THIS s.command_index = 0; - BX_FD_THIS s.command_size = 0; - BX_FD_THIS s.pending_command = 0; - - BX_FD_THIS s.floppy_buffer_index = 0; -} - diff --git a/tools/ioemu/iodev/floppy.h b/tools/ioemu/iodev/floppy.h deleted file mode 100644 index d874539900..0000000000 --- a/tools/ioemu/iodev/floppy.h +++ /dev/null @@ -1,138 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: floppy.h,v 1.16 2002/11/30 09:39:29 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - -#define FROM_FLOPPY 10 -#define TO_FLOPPY 11 - -#if BX_USE_FD_SMF -# define BX_FD_SMF static -# define BX_FD_THIS theFloppyController-> -#else -# define BX_FD_SMF -# define BX_FD_THIS this-> -#endif - -typedef struct { - int fd; /* file descriptor of floppy image file */ - unsigned sectors_per_track; /* number of sectors/track */ - unsigned sectors; /* number of formatted sectors on diskette */ - unsigned tracks; /* number of tracks */ - unsigned heads; /* number of heads */ - unsigned type; - unsigned write_protected; - } floppy_t; - -class bx_floppy_ctrl_c : public bx_floppy_stub_c { -public: - - bx_floppy_ctrl_c(void); - ~bx_floppy_ctrl_c(void); - virtual void init(void); - virtual void reset(unsigned type); - virtual unsigned set_media_status(unsigned drive, unsigned status); - virtual unsigned get_media_status(unsigned drive); - -private: - - struct { - Bit8u data_rate; - - Bit8u command[10]; /* largest command size ??? */ - Bit8u command_index; - Bit8u command_size; - bx_bool command_complete; - Bit8u pending_command; - - bx_bool multi_track; - bx_bool pending_irq; - Bit8u reset_sensei; - Bit8u format_count; - Bit8u format_fillbyte; - - Bit8u result[10]; - Bit8u result_index; - Bit8u result_size; - - Bit8u DOR; // Digital Ouput Register - Bit8u TDR; // Tape Drive Register - Bit8u cylinder[4]; // really only using 2 drives - Bit8u head[4]; // really only using 2 drives - Bit8u sector[4]; // really only using 2 drives - - /* MAIN STATUS REGISTER - * b7: MRQ: main request 1=data register ready 0=data register not ready - * b6: DIO: data input/output: - * 1=controller->CPU (ready for data read) - * 0=CPU->controller (ready for data write) - * b5: NDMA: non-DMA mode: 1=controller not in DMA modes - * 0=controller in DMA mode - * b4: BUSY: instruction(device busy) 1=active 0=not active - * b3-0: ACTD, ACTC, ACTB, ACTA: - * drive D,C,B,A in positioning mode 1=active 0=not active - */ - Bit8u main_status_reg; - - Bit8u status_reg0; - Bit8u status_reg1; - Bit8u status_reg2; - Bit8u status_reg3; - - // drive field allows up to 4 drives, even though probably only 2 will - // ever be used. - floppy_t media[4]; - unsigned num_supported_floppies; - Bit8u floppy_buffer[512+2]; // 2 extra for good measure - unsigned floppy_buffer_index; - int floppy_timer_index; - bx_bool media_present[2]; - Bit8u device_type[4]; - Bit8u DIR[4]; // Digital Input Register: - // b7: 0=diskette is present and has not been changed - // 1=diskette missing or changed - } s; // state information - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); -#if !BX_USE_FD_SMF - Bit32u read(Bit32u address, unsigned io_len); - void write(Bit32u address, Bit32u value, unsigned io_len); -#endif - BX_FD_SMF void dma_write(Bit8u *data_byte); - BX_FD_SMF void dma_read(Bit8u *data_byte); - BX_FD_SMF void floppy_command(void); - BX_FD_SMF void floppy_xfer(Bit8u drive, Bit32u offset, Bit8u *buffer, Bit32u bytes, Bit8u direction); - BX_FD_SMF void raise_interrupt(void); - BX_FD_SMF void enter_idle_phase(void); - BX_FD_SMF void enter_result_phase(void); - static void timer_handler(void *); - -public: - BX_FD_SMF void timer(void); - BX_FD_SMF void increment_sector(void); - BX_FD_SMF bx_bool evaluate_media(unsigned type, char *path, floppy_t *floppy); - }; diff --git a/tools/ioemu/iodev/gameport.cc b/tools/ioemu/iodev/gameport.cc deleted file mode 100644 index 9adefa6551..0000000000 --- a/tools/ioemu/iodev/gameport.cc +++ /dev/null @@ -1,242 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: gameport.cc,v 1.5 2003/12/29 21:48:56 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2003 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// -// Standard PC gameport -// - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" - -#ifdef __linux__ - -#include -#include -#include -#include -#include - -#elif defined(WIN32) - -#ifndef JOY_BUTTON1 -#define JOY_BUTTON1 1 -#define JOY_BUTTON2 2 -UINT STDCALL joyGetPos(UINT, LPJOYINFO); -#endif - -#define JOYSTICKID1 0 - -#endif - -#define LOG_THIS theGameport-> - -bx_gameport_c *theGameport = NULL; - - int -libgameport_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - theGameport = new bx_gameport_c (); - bx_devices.pluginGameport = theGameport; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theGameport, BX_PLUGIN_GAMEPORT); - return(0); // Success -} - - void -libgameport_LTX_plugin_fini(void) -{ -} - -bx_gameport_c::bx_gameport_c(void) -{ - put("GAME"); - settype(EXTFPUIRQLOG); -} - -bx_gameport_c::~bx_gameport_c(void) -{ - if (joyfd >= 0) close(joyfd); - BX_DEBUG(("Exit.")); -} - - - void -bx_gameport_c::init(void) -{ - // Allocate the gameport IO address range 0x200..0x207 - for (unsigned addr=0x200; addr<0x208; addr++) { - DEV_register_ioread_handler(this, read_handler, addr, "Gameport", 1); - DEV_register_iowrite_handler(this, write_handler, addr, "Gameport", 1); - } - - BX_GAMEPORT_THIS port = 0xf0; - BX_GAMEPORT_THIS write_usec = 0; - BX_GAMEPORT_THIS timer_x = 0; - BX_GAMEPORT_THIS timer_y = 0; - -#ifdef __linux__ - BX_GAMEPORT_THIS joyfd = open("/dev/input/js0", O_RDONLY); - if (BX_GAMEPORT_THIS joyfd >= 0) { - for (unsigned i=0; i<4; i++) poll_joydev(); - } -#elif defined(WIN32) - JOYINFO joypos; - if (joyGetPos(JOYSTICKID1, &joypos) == JOYERR_NOERROR) { - BX_GAMEPORT_THIS joyfd = 1; - } else { - BX_GAMEPORT_THIS joyfd = -1; - } -#else - BX_GAMEPORT_THIS joyfd = -1; -#endif -} - - void -bx_gameport_c::reset(unsigned type) -{ - // nothing for now -} - - void -bx_gameport_c::poll_joydev(void) -{ -#ifdef __linux__ - struct js_event e; - fd_set joyfds; - struct timeval tv; - - memset(&tv, 0, sizeof(tv)); - FD_ZERO(&joyfds); - FD_SET(BX_GAMEPORT_THIS joyfd, &joyfds); - e.type = 0; - if (select(BX_GAMEPORT_THIS joyfd+1, &joyfds, NULL, NULL, &tv)) { - read(BX_GAMEPORT_THIS joyfd, &e, sizeof(struct js_event)); - if (e.type & JS_EVENT_BUTTON) { - if (e.value == 1) { - BX_GAMEPORT_THIS port &= ~(0x10 << e.number); - } else { - BX_GAMEPORT_THIS port |= (0x10 << e.number); - } - } - if (e.type & JS_EVENT_AXIS) { - if (e.number == 0) { - BX_GAMEPORT_THIS delay_x = 25 + ((e.value + 0x8000) / 60); - } - if (e.number == 1) { - BX_GAMEPORT_THIS delay_y = 25 + ((e.value + 0x8000) / 62); - } - } - } -#elif defined(WIN32) - JOYINFO joypos; - if (joyGetPos(JOYSTICKID1, &joypos) == JOYERR_NOERROR) { - if (joypos.wButtons & JOY_BUTTON1) { - BX_GAMEPORT_THIS port &= ~0x10; - } else { - BX_GAMEPORT_THIS port |= 0x10; - } - if (joypos.wButtons & JOY_BUTTON2) { - BX_GAMEPORT_THIS port &= ~0x20; - } else { - BX_GAMEPORT_THIS port |= 0x20; - } - BX_GAMEPORT_THIS delay_x = 25 + (joypos.wXpos / 60); - BX_GAMEPORT_THIS delay_y = 25 + (joypos.wYpos / 60); - } -#endif -} - - - // static IO port read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_gameport_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_GAME_SMF - bx_gameport_c *class_ptr = (bx_gameport_c *) this_ptr; - - return( class_ptr->read(address, io_len) ); -} - - - Bit32u -bx_gameport_c::read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_GAME_SMF - Bit64u usec; - - if (BX_GAMEPORT_THIS joyfd >= 0) { - poll_joydev(); - usec = bx_pc_system.time_usec(); - if (BX_GAMEPORT_THIS timer_x) { - if ((usec - BX_GAMEPORT_THIS write_usec) >= BX_GAMEPORT_THIS delay_x) { - BX_GAMEPORT_THIS port &= 0xfe; - BX_GAMEPORT_THIS timer_x = 0; - } - } - if (BX_GAMEPORT_THIS timer_y) { - if ((usec - BX_GAMEPORT_THIS write_usec) >= BX_GAMEPORT_THIS delay_y) { - BX_GAMEPORT_THIS port &= 0xfd; - BX_GAMEPORT_THIS timer_y = 0; - } - } - } else { - BX_DEBUG(("read: joystick not present")); - } - return BX_GAMEPORT_THIS port; -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_gameport_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_GAME_SMF - bx_gameport_c *class_ptr = (bx_gameport_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - - void -bx_gameport_c::write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_GAME_SMF - - BX_GAMEPORT_THIS write_usec = bx_pc_system.time_usec(); - BX_GAMEPORT_THIS timer_x = 1; - BX_GAMEPORT_THIS timer_y = 1; - BX_GAMEPORT_THIS port |= 0x0f; -} diff --git a/tools/ioemu/iodev/gameport.h b/tools/ioemu/iodev/gameport.h deleted file mode 100644 index d4acdddf69..0000000000 --- a/tools/ioemu/iodev/gameport.h +++ /dev/null @@ -1,63 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: gameport.h,v 1.1 2003/06/21 12:55:19 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2003 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -#if BX_USE_GAME_SMF -# define BX_GAMEPORT_SMF static -# define BX_GAMEPORT_THIS theGameport-> -#else -# define BX_GAMEPORT_SMF -# define BX_GAMEPORT_THIS this-> -#endif - - -class bx_gameport_c : public bx_devmodel_c { - -public: - bx_gameport_c(void); - ~bx_gameport_c(void); - virtual void init(void); - virtual void reset(unsigned type); - -private: - - int joyfd; - Bit8u port; - Bit16u delay_x; - Bit16u delay_y; - bx_bool timer_x; - bx_bool timer_y; - Bit64u write_usec; - - BX_GAMEPORT_SMF void poll_joydev(void); - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); -#if !BX_USE_GAME_SMF - Bit32u read(Bit32u address, unsigned io_len); - void write(Bit32u address, Bit32u value, unsigned io_len); -#endif - }; diff --git a/tools/ioemu/iodev/guest2host.h b/tools/ioemu/iodev/guest2host.h deleted file mode 100644 index 0003662aa2..0000000000 --- a/tools/ioemu/iodev/guest2host.h +++ /dev/null @@ -1,77 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: guest2host.h,v 1.8 2002/12/06 18:48:08 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - -#define BX_MAX_G2H_CHANNELS 8 -#define BX_G2H_ERROR ((unsigned) -1) - // IO port number for this interface. Align on dword boundary. -#define BX_G2H_PORT 0x2000 - // Magic number which is first dword passed by guest -#define BX_G2H_MAGIC 0xffeeddcc - // Number of dwords in packet from guest -#define BX_G2H_PACKET_SIZE 5 - - - -typedef Bit32u bx_guest_packet_t[BX_G2H_PACKET_SIZE]; -typedef void (*bx_g2h_callback_t)(bx_guest_packet_t *); - - - -class bx_g2h_c : public logfunctions { -public: - bx_g2h_c(void); - ~bx_g2h_c(void); - static void init(void); - void reset (unsigned type); - unsigned acquire_channel(bx_g2h_callback_t); - unsigned deacquire_channel(unsigned channel); - -private: - - static Bit32u inp_handler(void *this_ptr, Bit32u addr, unsigned io_len); - static void outp_handler(void *this_ptr, Bit32u addr, - Bit32u value, unsigned io_len); - // state info - struct { - struct { - bx_g2h_callback_t f; - bx_bool used; - } callback[BX_MAX_G2H_CHANNELS]; - - // Define the data received from the guest OS. - // dword0: magic number, should be BX_G2H_MAGIC - // dword1: channel ID - // dword2: address of data structure in guest physical memory - // dword3: size of data structure in guest physical memory - // dword4: address of return data structure in guest physical memory - unsigned packet_count; - bx_guest_packet_t guest_packet; - } s; - }; - -extern bx_g2h_c bx_g2h; diff --git a/tools/ioemu/iodev/harddrv.cc b/tools/ioemu/iodev/harddrv.cc deleted file mode 100644 index cc44ce0871..0000000000 --- a/tools/ioemu/iodev/harddrv.cc +++ /dev/null @@ -1,4880 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: harddrv.cc,v 1.114.2.2 2004/02/06 22:14:35 danielg4 Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// Useful docs: -// AT Attachment with Packet Interface -// working draft by T13 at www.t13.org - - - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" - -#if BX_HAVE_SYS_MMAN_H -#include -#endif - -#define LOG_THIS theHardDrive-> - -// WARNING: dangerous options! -// These options provoke certain kinds of errors for testing purposes when they -// are set to a nonzero value. DO NOT ENABLE THEM when using any disk image -// you care about. -#define TEST_READ_BEYOND_END 0 -#define TEST_WRITE_BEYOND_END 0 -#ifdef __GNUC__ -# if TEST_READ_BEYOND_END || TEST_WRITE_BEYOND_END -# warning BEWARE: Dangerous options are enabled in harddrv.cc. If you are not trying to provoke hard drive errors you should disable them right now. -# endif -#endif -// end of dangerous options. - - -#define INDEX_PULSE_CYCLE 10 - -#define PACKET_SIZE 12 - -static unsigned max_multiple_sectors = 0; // was 0x3f -static unsigned curr_multiple_sectors = 0; // was 0x3f - -// some packet handling macros -#define EXTRACT_FIELD(arr,byte,start,num_bits) (((arr)[(byte)] >> (start)) & ((1 << (num_bits)) - 1)) -#define get_packet_field(c,b,s,n) (EXTRACT_FIELD((BX_SELECTED_CONTROLLER((c)).buffer),(b),(s),(n))) -#define get_packet_byte(c,b) (BX_SELECTED_CONTROLLER((c)).buffer[(b)]) -#define get_packet_word(c,b) (((uint16)BX_SELECTED_CONTROLLER((c)).buffer[(b)] << 8) | BX_SELECTED_CONTROLLER((c)).buffer[(b)+1]) - - -#define BX_CONTROLLER(c,a) (BX_HD_THIS channels[(c)].drives[(a)]).controller -#define BX_DRIVE(c,a) (BX_HD_THIS channels[(c)].drives[(a)]) - -#define BX_DRIVE_IS_PRESENT(c,a) (BX_HD_THIS channels[(c)].drives[(a)].device_type != IDE_NONE) -#define BX_DRIVE_IS_HD(c,a) (BX_HD_THIS channels[(c)].drives[(a)].device_type == IDE_DISK) -#define BX_DRIVE_IS_CD(c,a) (BX_HD_THIS channels[(c)].drives[(a)].device_type == IDE_CDROM) - -#define BX_MASTER_IS_PRESENT(c) BX_DRIVE_IS_PRESENT((c),0) -#define BX_SLAVE_IS_PRESENT(c) BX_DRIVE_IS_PRESENT((c),1) -#define BX_ANY_IS_PRESENT(c) (BX_DRIVE_IS_PRESENT((c),0) || BX_DRIVE_IS_PRESENT((c),1)) - -#define BX_SELECTED_CONTROLLER(c) (BX_CONTROLLER((c),BX_HD_THIS channels[(c)].drive_select)) -#define BX_SELECTED_DRIVE(c) (BX_DRIVE((c),BX_HD_THIS channels[(c)].drive_select)) -#define BX_MASTER_SELECTED(c) (!BX_HD_THIS channels[(c)].drive_select) -#define BX_SLAVE_SELECTED(c) (BX_HD_THIS channels[(c)].drive_select) - -#define BX_SELECTED_IS_PRESENT(c) (BX_DRIVE_IS_PRESENT((c),BX_SLAVE_SELECTED((c)))) -#define BX_SELECTED_IS_HD(c) (BX_DRIVE_IS_HD((c),BX_SLAVE_SELECTED((c)))) -#define BX_SELECTED_IS_CD(c) (BX_DRIVE_IS_CD((c),BX_SLAVE_SELECTED((c)))) - -#define BX_SELECTED_MODEL(c) (BX_HD_THIS channels[(c)].drives[BX_HD_THIS channels[(c)].drive_select].model_no) -#define BX_SELECTED_TYPE_STRING(channel) ((BX_SELECTED_IS_CD(channel)) ? "CD-ROM" : "DISK") - -#define WRITE_FEATURES(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).features = _a; BX_CONTROLLER((c),1).features = _a; } while(0) -#define WRITE_SECTOR_COUNT(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).sector_count = _a; BX_CONTROLLER((c),1).sector_count = _a; } while(0) -#define WRITE_SECTOR_NUMBER(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).sector_no = _a; BX_CONTROLLER((c),1).sector_no = _a; } while(0) -#define WRITE_CYLINDER_LOW(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).cylinder_no = (BX_CONTROLLER((c),0).cylinder_no & 0xff00) | _a; BX_CONTROLLER((c),1).cylinder_no = (BX_CONTROLLER((c),1).cylinder_no & 0xff00) | _a; } while(0) -#define WRITE_CYLINDER_HIGH(c,a) do { uint16 _a = a; BX_CONTROLLER((c),0).cylinder_no = (_a << 8) | (BX_CONTROLLER((c),0).cylinder_no & 0xff); BX_CONTROLLER((c),1).cylinder_no = (_a << 8) | (BX_CONTROLLER((c),1).cylinder_no & 0xff); } while(0) -#define WRITE_HEAD_NO(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).head_no = _a; BX_CONTROLLER((c),1).head_no = _a; } while(0) -#define WRITE_LBA_MODE(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).lba_mode = _a; BX_CONTROLLER((c),1).lba_mode = _a; } while(0) - -bx_hard_drive_c *theHardDrive = NULL; - - int -libharddrv_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - theHardDrive = new bx_hard_drive_c (); - bx_devices.pluginHardDrive = theHardDrive; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theHardDrive, BX_PLUGIN_HARDDRV); - return(0); // Success -} - - void -libharddrv_LTX_plugin_fini(void) -{ -} - -bx_hard_drive_c::bx_hard_drive_c(void) -{ -#if DLL_HD_SUPPORT -# error code must be fixed to use DLL_HD_SUPPORT and 4 ata channels -#endif - - for (Bit8u channel=0; channelget() == 1) { - BX_HD_THIS channels[channel].ioaddr1 = bx_options.ata[channel].Oioaddr1->get(); - BX_HD_THIS channels[channel].ioaddr2 = bx_options.ata[channel].Oioaddr2->get(); - BX_HD_THIS channels[channel].irq = bx_options.ata[channel].Oirq->get(); - - // Coherency check - if ( (BX_HD_THIS channels[channel].ioaddr1 == 0) || - (BX_HD_THIS channels[channel].ioaddr2 == 0) || - (BX_HD_THIS channels[channel].irq == 0) ) { - BX_PANIC(("incoherency for ata channel %d: io1=0x%x, io2=%x, irq=%d", - channel, - BX_HD_THIS channels[channel].ioaddr1, - BX_HD_THIS channels[channel].ioaddr2, - BX_HD_THIS channels[channel].irq)); - } - } - else { - BX_HD_THIS channels[channel].ioaddr1 = 0; - BX_HD_THIS channels[channel].ioaddr2 = 0; - BX_HD_THIS channels[channel].irq = 0; - } - } - - for (channel=0; channelget()) { - continue; - } - - // Make model string - strncpy((char*)BX_HD_THIS channels[channel].drives[device].model_no, - bx_options.atadevice[channel][device].Omodel->getptr(), 40); - while (strlen((char *)BX_HD_THIS channels[channel].drives[device].model_no) < 40) { - strcat ((char*)BX_HD_THIS channels[channel].drives[device].model_no, " "); - } - - if (bx_options.atadevice[channel][device].Otype->get() == BX_ATA_DEVICE_DISK) { - BX_DEBUG(( "Hard-Disk on target %d/%d",channel,device)); - BX_HD_THIS channels[channel].drives[device].device_type = IDE_DISK; - - int cyl = bx_options.atadevice[channel][device].Ocylinders->get (); - int heads = bx_options.atadevice[channel][device].Oheads->get (); - int spt = bx_options.atadevice[channel][device].Ospt->get (); - Bit64u disk_size = (Bit64u)cyl * heads * spt * 512; - - /* instantiate the right class */ - switch (bx_options.atadevice[channel][device].Omode->get()) { - - case BX_ATA_MODE_FLAT: - BX_INFO(("HD on ata%d-%d: '%s' 'flat' mode ", channel, device, - bx_options.atadevice[channel][device].Opath->getptr ())); - channels[channel].drives[device].hard_drive = new default_image_t(); - break; - - case BX_ATA_MODE_CONCAT: - BX_INFO(("HD on ata%d-%d: '%s' 'concat' mode ", channel, device, - bx_options.atadevice[channel][device].Opath->getptr ())); - channels[channel].drives[device].hard_drive = new concat_image_t(); - break; - -#if EXTERNAL_DISK_SIMULATOR - case BX_ATA_MODE_EXTDISKSIM: - BX_INFO(("HD on ata%d-%d: '%s' 'External Simulator' mode ", channel, device, - bx_options.atadevice[channel][device].Opath->getptr ())); - channels[channel].drives[device].hard_drive = new EXTERNAL_DISK_SIMULATOR_CLASS(); - break; -#endif //EXTERNAL_DISK_SIMULATOR - -#if DLL_HD_SUPPORT - case BX_ATA_MODE_DLL_HD: - BX_INFO(("HD on ata%d-%d: '%s' 'dll' mode ", channel, device, - bx_options.atadevice[channel][device].Opath->getptr ())); - channels[channel].drives[device].hard_drive = new dll_image_t(); - break; -#endif //DLL_HD_SUPPORT - - case BX_ATA_MODE_SPARSE: - BX_INFO(("HD on ata%d-%d: '%s' 'sparse' mode ", channel, device, - bx_options.atadevice[channel][device].Opath->getptr ())); - channels[channel].drives[device].hard_drive = new sparse_image_t(); - break; - -#if 0 - case BX_ATA_MODE_VMWARE3: - BX_INFO(("HD on ata%d-%d: '%s' 'vmware3' mode ", channel, device, - bx_options.atadevice[channel][device].Opath->getptr ())); - channels[channel].drives[device].hard_drive = new vmware3_image_t(); - break; - - case BX_ATA_MODE_SPLIT: - BX_INFO(("HD on ata%d-%d: '%s' 'split' mode ", channel, device, - bx_options.atadevice[channel][device].Opath->getptr ())); - channels[channel].drives[device].hard_drive = new split_image_t(); - break; -#endif - - case BX_ATA_MODE_UNDOABLE: - BX_INFO(("HD on ata%d-%d: '%s' 'undoable' mode ", channel, device, - bx_options.atadevice[channel][device].Opath->getptr ())); - channels[channel].drives[device].hard_drive = new undoable_image_t(disk_size, - bx_options.atadevice[channel][device].Ojournal->getptr()); - break; - - case BX_ATA_MODE_GROWING: - BX_INFO(("HD on ata%d-%d: '%s' 'growing' mode ", channel, device, - bx_options.atadevice[channel][device].Opath->getptr ())); - channels[channel].drives[device].hard_drive = new growing_image_t(disk_size); - break; - - case BX_ATA_MODE_VOLATILE: - BX_INFO(("HD on ata%d-%d: '%s' 'volatile' mode ", channel, device, - bx_options.atadevice[channel][device].Opath->getptr ())); - channels[channel].drives[device].hard_drive = new volatile_image_t(disk_size, - bx_options.atadevice[channel][device].Ojournal->getptr()); - break; - -#if 0 -#if BX_COMPRESSED_HD_SUPPORT - case BX_ATA_MODE_Z_UNDOABLE: - BX_PANIC(("z-undoable disk support not implemented")); - BX_INFO(("HD on ata%d-%d: '%s' 'z-undoable' mode ", channel, device, - bx_options.atadevice[channel][device].Opath->getptr ())); - channels[channel].drives[device].hard_drive = new z_undoable_image_t(disk_size, - bx_options.atadevice[channel][device].Ojournal->getptr()); - break; - - case BX_ATA_MODE_Z_VOLATILE: - BX_PANIC(("z-volatile disk support not implemented")); - BX_INFO(("HD on ata%d-%d: '%s' 'z-volatile' mode ", channel, device, - bx_options.atadevice[channel][device].Opath->getptr ())); - channels[channel].drives[device].hard_drive = new z_volatile_image_t(disk_size, - bx_options.atadevice[channel][device].Ojournal->getptr()); - break; -#endif //BX_COMPRESSED_HD_SUPPORT -#endif - - default: - BX_PANIC(("HD on ata%d-%d: '%s' unsupported HD mode : %s", channel, device, - bx_options.atadevice[channel][device].Opath->getptr (), - atadevice_mode_names[bx_options.atadevice[channel][device].Omode->get()])); - break; - } - - BX_HD_THIS channels[channel].drives[device].hard_drive->cylinders = cyl; - BX_HD_THIS channels[channel].drives[device].hard_drive->heads = heads; - BX_HD_THIS channels[channel].drives[device].hard_drive->sectors = spt; - - if (cyl == 0 || heads == 0 || spt == 0) { - BX_PANIC(("ata%d/%d cannot have zero cylinders, heads, or sectors/track", channel, device)); - } - - /* open hard drive image file */ - if ((BX_HD_THIS channels[channel].drives[device].hard_drive->open(bx_options.atadevice[channel][device].Opath->getptr ())) < 0) { - BX_PANIC(("ata%d-%d: could not open hard drive image file '%s'", channel, device, bx_options.atadevice[channel][device].Opath->getptr ())); - } - } - else if (bx_options.atadevice[channel][device].Otype->get() == BX_ATA_DEVICE_CDROM) { - BX_DEBUG(( "CDROM on target %d/%d",channel,device)); - BX_HD_THIS channels[channel].drives[device].device_type = IDE_CDROM; - BX_HD_THIS channels[channel].drives[device].cdrom.locked = 0; - BX_HD_THIS channels[channel].drives[device].sense.sense_key = SENSE_NONE; - BX_HD_THIS channels[channel].drives[device].sense.asc = 0; - BX_HD_THIS channels[channel].drives[device].sense.ascq = 0; - - // Check bit fields - BX_CONTROLLER(channel,device).sector_count = 0; - BX_CONTROLLER(channel,device).interrupt_reason.c_d = 1; - if (BX_CONTROLLER(channel,device).sector_count != 0x01) - BX_PANIC(("interrupt reason bit field error")); - - BX_CONTROLLER(channel,device).sector_count = 0; - BX_CONTROLLER(channel,device).interrupt_reason.i_o = 1; - if (BX_CONTROLLER(channel,device).sector_count != 0x02) - BX_PANIC(("interrupt reason bit field error")); - - BX_CONTROLLER(channel,device).sector_count = 0; - BX_CONTROLLER(channel,device).interrupt_reason.rel = 1; - if (BX_CONTROLLER(channel,device).sector_count != 0x04) - BX_PANIC(("interrupt reason bit field error")); - - BX_CONTROLLER(channel,device).sector_count = 0; - BX_CONTROLLER(channel,device).interrupt_reason.tag = 3; - if (BX_CONTROLLER(channel,device).sector_count != 0x18) - BX_PANIC(("interrupt reason bit field error")); - BX_CONTROLLER(channel,device).sector_count = 0; - - // allocate low level driver -#ifdef LOWLEVEL_CDROM - BX_HD_THIS channels[channel].drives[device].cdrom.cd = new LOWLEVEL_CDROM(bx_options.atadevice[channel][device].Opath->getptr ()); - BX_INFO(("CD on ata%d-%d: '%s'",channel, device, bx_options.atadevice[channel][device].Opath->getptr ())); - - if (bx_options.atadevice[channel][device].Ostatus->get () == BX_INSERTED) { - if (BX_HD_THIS channels[channel].drives[device].cdrom.cd->insert_cdrom()) { - BX_INFO(( "Media present in CD-ROM drive")); - BX_HD_THIS channels[channel].drives[device].cdrom.ready = 1; - BX_HD_THIS channels[channel].drives[device].cdrom.capacity = BX_HD_THIS channels[channel].drives[device].cdrom.cd->capacity(); - } else { - BX_INFO(( "Could not locate CD-ROM, continuing with media not present")); - BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0; - bx_options.atadevice[channel][device].Ostatus->set(BX_EJECTED); - } - } else { -#endif - BX_INFO(( "Media not present in CD-ROM drive" )); - BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0; -#ifdef LOWLEVEL_CDROM - } -#endif - } - } - } - -#if BX_PDC20230C_VLBIDE_SUPPORT - BX_HD_THIS pdc20230c.prog_mode = 0; - BX_HD_THIS pdc20230c.prog_count = 0; - BX_HD_THIS pdc20230c.p1f3_value = 0; - BX_HD_THIS pdc20230c.p1f4_value = 0; -#endif - - - // generate CMOS values for hard drive if not using a CMOS image - if (!bx_options.cmos.OcmosImage->get ()) { - DEV_cmos_set_reg(0x12, 0x00); // start out with: no drive 0, no drive 1 - - if (BX_DRIVE_IS_HD(0,0)) { - // Flag drive type as Fh, use extended CMOS location as real type - DEV_cmos_set_reg(0x12, (DEV_cmos_get_reg(0x12) & 0x0f) | 0xf0); - DEV_cmos_set_reg(0x19, 47); // user definable type - // AMI BIOS: 1st hard disk #cyl low byte - DEV_cmos_set_reg(0x1b, (bx_options.atadevice[0][0].Ocylinders->get () & 0x00ff)); - // AMI BIOS: 1st hard disk #cyl high byte - DEV_cmos_set_reg(0x1c, (bx_options.atadevice[0][0].Ocylinders->get () & 0xff00) >> 8); - // AMI BIOS: 1st hard disk #heads - DEV_cmos_set_reg(0x1d, (bx_options.atadevice[0][0].Oheads->get ())); - // AMI BIOS: 1st hard disk write precompensation cylinder, low byte - DEV_cmos_set_reg(0x1e, 0xff); // -1 - // AMI BIOS: 1st hard disk write precompensation cylinder, high byte - DEV_cmos_set_reg(0x1f, 0xff); // -1 - // AMI BIOS: 1st hard disk control byte - DEV_cmos_set_reg(0x20, (0xc0 | ((bx_options.atadevice[0][0].Oheads->get () > 8) << 3))); - // AMI BIOS: 1st hard disk landing zone, low byte - DEV_cmos_set_reg(0x21, DEV_cmos_get_reg(0x1b)); - // AMI BIOS: 1st hard disk landing zone, high byte - DEV_cmos_set_reg(0x22, DEV_cmos_get_reg(0x1c)); - // AMI BIOS: 1st hard disk sectors/track - DEV_cmos_set_reg(0x23, bx_options.atadevice[0][0].Ospt->get ()); - } - - //set up cmos for second hard drive - if (BX_DRIVE_IS_HD(0,1)) { - BX_DEBUG(("1: I will put 0xf into the second hard disk field")); - // fill in lower 4 bits of 0x12 for second HD - DEV_cmos_set_reg(0x12, (DEV_cmos_get_reg(0x12) & 0xf0) | 0x0f); - DEV_cmos_set_reg(0x1a, 47); // user definable type - // AMI BIOS: 2nd hard disk #cyl low byte - DEV_cmos_set_reg(0x24, (bx_options.atadevice[0][1].Ocylinders->get () & 0x00ff)); - // AMI BIOS: 2nd hard disk #cyl high byte - DEV_cmos_set_reg(0x25, (bx_options.atadevice[0][1].Ocylinders->get () & 0xff00) >> 8); - // AMI BIOS: 2nd hard disk #heads - DEV_cmos_set_reg(0x26, (bx_options.atadevice[0][1].Oheads->get ())); - // AMI BIOS: 2nd hard disk write precompensation cylinder, low byte - DEV_cmos_set_reg(0x27, 0xff); // -1 - // AMI BIOS: 2nd hard disk write precompensation cylinder, high byte - DEV_cmos_set_reg(0x28, 0xff); // -1 - // AMI BIOS: 2nd hard disk, 0x80 if heads>8 - DEV_cmos_set_reg(0x29, (bx_options.atadevice[0][1].Oheads->get () > 8) ? 0x80 : 0x00); - // AMI BIOS: 2nd hard disk landing zone, low byte - DEV_cmos_set_reg(0x2a, DEV_cmos_get_reg(0x24)); - // AMI BIOS: 2nd hard disk landing zone, high byte - DEV_cmos_set_reg(0x2b, DEV_cmos_get_reg(0x25)); - // AMI BIOS: 2nd hard disk sectors/track - DEV_cmos_set_reg(0x2c, bx_options.atadevice[0][1].Ospt->get ()); - } - - DEV_cmos_set_reg(0x39, 0); - DEV_cmos_set_reg(0x3a, 0); - for (channel=0; channelget()) { - if (BX_DRIVE_IS_HD(channel,device)) { - Bit16u cylinders = bx_options.atadevice[channel][device].Ocylinders->get(); - Bit16u heads = bx_options.atadevice[channel][device].Oheads->get(); - Bit16u spt = bx_options.atadevice[channel][device].Ospt->get(); - Bit8u translation = bx_options.atadevice[channel][device].Otranslation->get(); - - Bit8u reg = 0x39 + channel/2; - Bit8u bitshift = 2 * (device+(2 * (channel%2))); - - // Find the right translation if autodetect - if (translation == BX_ATA_TRANSLATION_AUTO) { - if((cylinders <= 1024) && (heads <= 16) && (spt <= 63)) { - translation = BX_ATA_TRANSLATION_NONE; - } - else if (((Bit32u)cylinders * (Bit32u)heads) <= 131072) { - translation = BX_ATA_TRANSLATION_LARGE; - } - else translation = BX_ATA_TRANSLATION_LBA; - - BX_INFO(("translation on ata%d-%d set to '%s'",channel, device, - translation==BX_ATA_TRANSLATION_NONE?"none": - translation==BX_ATA_TRANSLATION_LARGE?"large": - "lba")); - } - - // FIXME we should test and warn - // - if LBA and spt != 63 - // - if RECHS and heads != 16 - // - if NONE and size > 1024*16*SPT blocks - // - if LARGE and size > 8192*16*SPT blocks - // - if RECHS and size > 1024*240*SPT blocks - // - if LBA and size > 1024*255*63, not that we can do much about it - - switch(translation) { - case BX_ATA_TRANSLATION_NONE: - DEV_cmos_set_reg(reg, DEV_cmos_get_reg(reg) | (0 << bitshift)); - break; - case BX_ATA_TRANSLATION_LBA: - DEV_cmos_set_reg(reg, DEV_cmos_get_reg(reg) | (1 << bitshift)); - break; - case BX_ATA_TRANSLATION_LARGE: - DEV_cmos_set_reg(reg, DEV_cmos_get_reg(reg) | (2 << bitshift)); - break; - case BX_ATA_TRANSLATION_RECHS: - DEV_cmos_set_reg(reg, DEV_cmos_get_reg(reg) | (3 << bitshift)); - break; - } - } - } - } - } - - // Set the "non-extended" boot device. This will default to DISKC if cdrom - if ( bx_options.Obootdrive->get () != BX_BOOT_FLOPPYA) { - // system boot sequence C:, A: - DEV_cmos_set_reg(0x2d, DEV_cmos_get_reg(0x2d) & 0xdf); - } - else { // 'a' - // system boot sequence A:, C: - DEV_cmos_set_reg(0x2d, DEV_cmos_get_reg(0x2d) | 0x20); - } - - // Set the "extended" boot device, byte 0x3D (needed for cdrom booting) - if ( bx_options.Obootdrive->get () == BX_BOOT_FLOPPYA) { - // system boot sequence A: - DEV_cmos_set_reg(0x3d, 0x01); - BX_INFO(("Boot device will be 'a'")); - } - else if ( bx_options.Obootdrive->get () == BX_BOOT_DISKC) { - // system boot sequence C: - DEV_cmos_set_reg(0x3d, 0x02); - BX_INFO(("Boot device will be 'c'")); - } - else if ( bx_options.Obootdrive->get () == BX_BOOT_CDROM) { - // system boot sequence cdrom - DEV_cmos_set_reg(0x3d, 0x03); - BX_INFO(("Boot device will be 'cdrom'")); - } - - // Set the signature check flag in cmos, inverted for compatibility - DEV_cmos_set_reg(0x38, bx_options.OfloppySigCheck->get()); - BX_INFO(("Floppy boot signature check is %sabled", bx_options.OfloppySigCheck->get() ? "dis" : "en")); - } - -} - - void -bx_hard_drive_c::reset(unsigned type) -{ - for (unsigned channel=0; channelread(address, io_len) ); -} - - - Bit32u -bx_hard_drive_c::read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_HD_SMF - Bit8u value8; - Bit16u value16; - Bit32u value32; - - Bit8u channel = BX_MAX_ATA_CHANNEL; - Bit32u port = 0xff; // undefined - - for (channel=0; channel 0x03f7)) { - BX_PANIC(("read: unable to find ATA channel, ioport=0x%04x", address)); - } else { - channel = 0; - port = address - 0x03e0; - } - } - -#if BX_PDC20230C_VLBIDE_SUPPORT -// pdc20230c is only available for first ata channel -if (channel == 0) { - - // Detect the switch to programming mode - if (!BX_HD_THIS pdc20230c.prog_mode) { - switch (port) { - case 0x02: - if ((BX_HD_THIS pdc20230c.prog_count == 0) || (BX_HD_THIS pdc20230c.prog_count > 2)) { - BX_HD_THIS pdc20230c.prog_count++; - } - else { - BX_HD_THIS pdc20230c.prog_count=0; - } - break; - case 0x16: - if ((BX_HD_THIS pdc20230c.prog_count == 1) || (BX_HD_THIS pdc20230c.prog_count == 2)) { - BX_HD_THIS pdc20230c.prog_count++; - } - else { - BX_HD_THIS pdc20230c.prog_count=0; - } - break; - default: - BX_HD_THIS pdc20230c.prog_count=0; - } - - if (BX_HD_THIS pdc20230c.prog_count == 5) { - BX_HD_THIS pdc20230c.prog_mode = 1; - BX_SELECTED_CONTROLLER(channel).sector_count &= 0x7f; - BX_INFO(("Promise VLB-IDE DC2300: Switching to Programming mode")); - } - } - - // Returns value when in programming mode - if (BX_HD_THIS pdc20230c.prog_mode) { - switch (port) { - case 0x05: - // Leave programming mode - BX_HD_THIS pdc20230c.prog_mode = 0; - BX_INFO(("Promise VLB-IDE DC2300: Leaving Programming mode")); - // Value will be sent be normal code - break; - case 0x03: - // Special programming register - value32 = BX_HD_THIS pdc20230c.p1f3_value; - GOTO_RETURN_VALUE ; - break; - case 0x04: - // Special programming register - value32 = BX_HD_THIS pdc20230c.p1f4_value; - GOTO_RETURN_VALUE ; - break; - } - } -} -#endif - - switch (port) { - case 0x00: // hard disk data (16bit) 0x1f0 - if (BX_SELECTED_CONTROLLER(channel).status.drq == 0) { - BX_ERROR(("IO read(0x%04x) with drq == 0: last command was %02xh", - address, (unsigned) BX_SELECTED_CONTROLLER(channel).current_command)); - return(0); - } - BX_DEBUG(("IO read(0x%04x): current command is %02xh", - address, (unsigned) BX_SELECTED_CONTROLLER(channel).current_command)); - switch (BX_SELECTED_CONTROLLER(channel).current_command) { - case 0x20: // READ SECTORS, with retries - case 0x21: // READ SECTORS, without retries - if (BX_SELECTED_CONTROLLER(channel).buffer_index >= 512) - BX_PANIC(("IO read(0x%04x): buffer_index >= 512", address)); - -#if BX_SupportRepeatSpeedups - if (DEV_bulk_io_quantum_requested()) { - unsigned transferLen, quantumsMax; - - quantumsMax = - (512 - BX_SELECTED_CONTROLLER(channel).buffer_index) / io_len; - if ( quantumsMax == 0) - BX_PANIC(("IO read(0x%04x): not enough space for read", address)); - DEV_bulk_io_quantum_transferred() = - DEV_bulk_io_quantum_requested(); - if (quantumsMax < DEV_bulk_io_quantum_transferred()) - DEV_bulk_io_quantum_transferred() = quantumsMax; - transferLen = io_len * DEV_bulk_io_quantum_transferred(); - memcpy((Bit8u*) DEV_bulk_io_host_addr(), - &BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index], - transferLen); - DEV_bulk_io_host_addr() += transferLen; - BX_SELECTED_CONTROLLER(channel).buffer_index += transferLen; - value32 = 0; // Value returned not important; - } - else -#endif - { - value32 = 0L; - switch(io_len){ - case 4: - value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+3] << 24); - value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+2] << 16); - case 2: - value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+1] << 8); - value32 |= BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index]; - } - BX_SELECTED_CONTROLLER(channel).buffer_index += io_len; - } - - // if buffer completely read - if (BX_SELECTED_CONTROLLER(channel).buffer_index >= 512) { - // update sector count, sector number, cylinder, - // drive, head, status - // if there are more sectors, read next one in... - // - BX_SELECTED_CONTROLLER(channel).buffer_index = 0; - - increment_address(channel); - - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; - if (bx_options.OnewHardDriveSupport->get ()) - BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; - else - BX_SELECTED_CONTROLLER(channel).status.seek_complete = 0; - BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - - if (BX_SELECTED_CONTROLLER(channel).sector_count==0) { - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - } - else { /* read next one into controller buffer */ - off_t logical_sector; - off_t ret; - - BX_SELECTED_CONTROLLER(channel).status.drq = 1; - BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; - -#if TEST_READ_BEYOND_END==1 - BX_SELECTED_CONTROLLER(channel).cylinder_no += 100000; -#endif - if (!calculate_logical_address(channel, &logical_sector)) { - BX_ERROR(("multi-sector read reached invalid sector %lu, aborting", (unsigned long)logical_sector)); - command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command); - GOTO_RETURN_VALUE ; - } - ret = BX_SELECTED_DRIVE(channel).hard_drive->lseek(logical_sector * 512, SEEK_SET); - if (ret < 0) { - BX_ERROR(("could not lseek() hard drive image file")); - command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command); - GOTO_RETURN_VALUE ; - } - ret = BX_SELECTED_DRIVE(channel).hard_drive->read((bx_ptr_t) BX_SELECTED_CONTROLLER(channel).buffer, 512); - if (ret < 512) { - BX_ERROR(("logical sector was %lu", (unsigned long)logical_sector)); - BX_ERROR(("could not read() hard drive image file at byte %lu", (unsigned long)logical_sector*512)); - command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command); - GOTO_RETURN_VALUE ; - } - - BX_SELECTED_CONTROLLER(channel).buffer_index = 0; - raise_interrupt(channel); - } - } - GOTO_RETURN_VALUE ; - break; - - case 0xec: // IDENTIFY DEVICE - case 0xa1: - if (bx_options.OnewHardDriveSupport->get ()) { - unsigned index; - - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; - BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; - BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - - index = BX_SELECTED_CONTROLLER(channel).buffer_index; - value32 = BX_SELECTED_CONTROLLER(channel).buffer[index]; - index++; - if (io_len >= 2) { - value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index] << 8); - index++; - } - if (io_len == 4) { - value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index] << 16); - value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index+1] << 24); - index += 2; - } - BX_SELECTED_CONTROLLER(channel).buffer_index = index; - - if (BX_SELECTED_CONTROLLER(channel).buffer_index >= 512) { - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) - BX_INFO(("Read all drive ID Bytes ...")); - } - GOTO_RETURN_VALUE; - } - else - BX_PANIC(("IO read(0x%04x): current command is %02xh", address, - (unsigned) BX_SELECTED_CONTROLLER(channel).current_command)); - - case 0xa0: { - unsigned index = BX_SELECTED_CONTROLLER(channel).buffer_index; - unsigned increment = 0; - - // Load block if necessary - if (index >= 2048) { - if (index > 2048) - BX_PANIC(("index > 2048 : 0x%x",index)); - switch (BX_SELECTED_DRIVE(channel).atapi.command) { - case 0x28: // read (10) - case 0xa8: // read (12) -#ifdef LOWLEVEL_CDROM - if (!BX_SELECTED_DRIVE(channel).cdrom.ready) { - BX_PANIC(("Read with CDROM not ready")); - } - BX_SELECTED_DRIVE(channel).cdrom.cd->read_block(BX_SELECTED_CONTROLLER(channel).buffer, - BX_SELECTED_DRIVE(channel).cdrom.next_lba); - BX_SELECTED_DRIVE(channel).cdrom.next_lba++; - BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks--; - - if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) - if (!BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks) - BX_INFO(("Last READ block loaded {CDROM}")); - else - BX_INFO(("READ block loaded (%d remaining) {CDROM}", - BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks)); - - // one block transfered, start at beginning - index = 0; -#else - BX_PANIC(("Read with no LOWLEVEL_CDROM")); -#endif - break; - - default: // no need to load a new block - break; - } - } - - value32 = BX_SELECTED_CONTROLLER(channel).buffer[index+increment]; - increment++; - if (io_len >= 2) { - value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index+increment] << 8); - increment++; - } - if (io_len == 4) { - value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index+increment] << 16); - value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index+increment+1] << 24); - increment += 2; - } - BX_SELECTED_CONTROLLER(channel).buffer_index = index + increment; - BX_SELECTED_CONTROLLER(channel).drq_index += increment; - - if (BX_SELECTED_CONTROLLER(channel).drq_index >= (unsigned)BX_SELECTED_DRIVE(channel).atapi.drq_bytes) { - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).drq_index = 0; - - BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining -= BX_SELECTED_DRIVE(channel).atapi.drq_bytes; - - if (BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining > 0) { - // one or more blocks remaining (works only for single block commands) - if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) - BX_INFO(("PACKET drq bytes read")); - BX_SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1; - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drq = 1; - BX_SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 0; - - // set new byte count if last block - if (BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining < BX_SELECTED_CONTROLLER(channel).byte_count) { - BX_SELECTED_CONTROLLER(channel).byte_count = BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining; - } - BX_SELECTED_DRIVE(channel).atapi.drq_bytes = BX_SELECTED_CONTROLLER(channel).byte_count; - - raise_interrupt(channel); - } else { - // all bytes read - if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) - BX_INFO(("PACKET all bytes read")); - BX_SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1; - BX_SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 1; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).interrupt_reason.rel = 0; - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - - raise_interrupt(channel); - } - } - GOTO_RETURN_VALUE; - break; - } - - // List all the read operations that are defined in the ATA/ATAPI spec - // that we don't support. Commands that are listed here will cause a - // BX_ERROR, which is non-fatal, and the command will be aborted. - case 0x08: BX_ERROR(("read cmd 0x08 (DEVICE RESET) not supported")); command_aborted(channel, 0x08); break; - case 0x10: BX_ERROR(("read cmd 0x10 (RECALIBRATE) not supported")); command_aborted(channel, 0x10); break; - case 0x22: BX_ERROR(("read cmd 0x22 (READ LONG) not supported")); command_aborted(channel, 0x22); break; - case 0x23: BX_ERROR(("read cmd 0x23 (READ LONG NO RETRY) not supported")); command_aborted(channel, 0x23); break; - case 0x24: BX_ERROR(("read cmd 0x24 (READ SECTORS EXT) not supported")); command_aborted(channel, 0x24); break; - case 0x25: BX_ERROR(("read cmd 0x25 (READ DMA EXT) not supported")); command_aborted(channel, 0x25); break; - case 0x26: BX_ERROR(("read cmd 0x26 (READ DMA QUEUED EXT) not supported")); command_aborted(channel, 0x26); break; - case 0x27: BX_ERROR(("read cmd 0x27 (READ NATIVE MAX ADDRESS EXT) not supported")); command_aborted(channel, 0x27); break; - case 0x29: BX_ERROR(("read cmd 0x29 (READ MULTIPLE EXT) not supported")); command_aborted(channel, 0x29); break; - case 0x2A: BX_ERROR(("read cmd 0x2A (READ STREAM DMA) not supported")); command_aborted(channel, 0x2A); break; - case 0x2B: BX_ERROR(("read cmd 0x2B (READ STREAM PIO) not supported")); command_aborted(channel, 0x2B); break; - case 0x2F: BX_ERROR(("read cmd 0x2F (READ LOG EXT) not supported")); command_aborted(channel, 0x2F); break; - case 0x30: BX_ERROR(("read cmd 0x30 (WRITE SECTORS) not supported")); command_aborted(channel, 0x30); break; - case 0x31: BX_ERROR(("read cmd 0x31 (WRITE SECTORS NO RETRY) not supported")); command_aborted(channel, 0x31); break; - case 0x32: BX_ERROR(("read cmd 0x32 (WRITE LONG) not supported")); command_aborted(channel, 0x32); break; - case 0x33: BX_ERROR(("read cmd 0x33 (WRITE LONG NO RETRY) not supported")); command_aborted(channel, 0x33); break; - case 0x34: BX_ERROR(("read cmd 0x34 (WRITE SECTORS EXT) not supported")); command_aborted(channel, 0x34); break; - case 0x35: BX_ERROR(("read cmd 0x35 (WRITE DMA EXT) not supported")); command_aborted(channel, 0x35); break; - case 0x36: BX_ERROR(("read cmd 0x36 (WRITE DMA QUEUED EXT) not supported")); command_aborted(channel, 0x36); break; - case 0x37: BX_ERROR(("read cmd 0x37 (SET MAX ADDRESS EXT) not supported")); command_aborted(channel, 0x37); break; - case 0x38: BX_ERROR(("read cmd 0x38 (CFA WRITE SECTORS W/OUT ERASE) not supported")); command_aborted(channel, 0x38); break; - case 0x39: BX_ERROR(("read cmd 0x39 (WRITE MULTIPLE EXT) not supported")); command_aborted(channel, 0x39); break; - case 0x3A: BX_ERROR(("read cmd 0x3A (WRITE STREAM DMA) not supported")); command_aborted(channel, 0x3A); break; - case 0x3B: BX_ERROR(("read cmd 0x3B (WRITE STREAM PIO) not supported")); command_aborted(channel, 0x3B); break; - case 0x3F: BX_ERROR(("read cmd 0x3F (WRITE LOG EXT) not supported")); command_aborted(channel, 0x3F); break; - case 0x40: BX_ERROR(("read cmd 0x40 (READ VERIFY SECTORS) not supported")); command_aborted(channel, 0x40); break; - case 0x41: BX_ERROR(("read cmd 0x41 (READ VERIFY SECTORS NO RETRY) not supported")); command_aborted(channel, 0x41); break; - case 0x42: BX_ERROR(("read cmd 0x42 (READ VERIFY SECTORS EXT) not supported")); command_aborted(channel, 0x42); break; - case 0x50: BX_ERROR(("read cmd 0x50 (FORMAT TRACK) not supported")); command_aborted(channel, 0x50); break; - case 0x51: BX_ERROR(("read cmd 0x51 (CONFIGURE STREAM) not supported")); command_aborted(channel, 0x51); break; - case 0x70: BX_ERROR(("read cmd 0x70 (SEEK) not supported")); command_aborted(channel, 0x70); break; - case 0x87: BX_ERROR(("read cmd 0x87 (CFA TRANSLATE SECTOR) not supported")); command_aborted(channel, 0x87); break; - case 0x90: BX_ERROR(("read cmd 0x90 (EXECUTE DEVICE DIAGNOSTIC) not supported")); command_aborted(channel, 0x90); break; - case 0x91: BX_ERROR(("read cmd 0x91 (INITIALIZE DEVICE PARAMETERS) not supported")); command_aborted(channel, 0x91); break; - case 0x92: BX_ERROR(("read cmd 0x92 (DOWNLOAD MICROCODE) not supported")); command_aborted(channel, 0x92); break; - case 0x94: BX_ERROR(("read cmd 0x94 (STANDBY IMMEDIATE) not supported")); command_aborted(channel, 0x94); break; - case 0x95: BX_ERROR(("read cmd 0x95 (IDLE IMMEDIATE) not supported")); command_aborted(channel, 0x95); break; - case 0x96: BX_ERROR(("read cmd 0x96 (STANDBY) not supported")); command_aborted(channel, 0x96); break; - case 0x97: BX_ERROR(("read cmd 0x97 (IDLE) not supported")); command_aborted(channel, 0x97); break; - case 0x98: BX_ERROR(("read cmd 0x98 (CHECK POWER MODE) not supported")); command_aborted(channel, 0x98); break; - case 0x99: BX_ERROR(("read cmd 0x99 (SLEEP) not supported")); command_aborted(channel, 0x99); break; - case 0xA2: BX_ERROR(("read cmd 0xA2 (SERVICE) not supported")); command_aborted(channel, 0xA2); break; - case 0xB0: BX_ERROR(("read cmd 0xB0 (SMART DISABLE OPERATIONS) not supported")); command_aborted(channel, 0xB0); break; - case 0xB1: BX_ERROR(("read cmd 0xB1 (DEVICE CONFIGURATION FREEZE LOCK) not supported")); command_aborted(channel, 0xB1); break; - case 0xC0: BX_ERROR(("read cmd 0xC0 (CFA ERASE SECTORS) not supported")); command_aborted(channel, 0xC0); break; - case 0xC4: BX_ERROR(("read cmd 0xC4 (READ MULTIPLE) not supported")); command_aborted(channel, 0xC4); break; - case 0xC5: BX_ERROR(("read cmd 0xC5 (WRITE MULTIPLE) not supported")); command_aborted(channel, 0xC5); break; - case 0xC6: BX_ERROR(("read cmd 0xC6 (SET MULTIPLE MODE) not supported")); command_aborted(channel, 0xC6); break; - case 0xC7: BX_ERROR(("read cmd 0xC7 (READ DMA QUEUED) not supported")); command_aborted(channel, 0xC7); break; - case 0xC8: BX_ERROR(("read cmd 0xC8 (READ DMA) not supported")); command_aborted(channel, 0xC8); break; - case 0xC9: BX_ERROR(("read cmd 0xC9 (READ DMA NO RETRY) not supported")); command_aborted(channel, 0xC9); break; - case 0xCA: BX_ERROR(("read cmd 0xCA (WRITE DMA) not supported")); command_aborted(channel, 0xCA); break; - case 0xCC: BX_ERROR(("read cmd 0xCC (WRITE DMA QUEUED) not supported")); command_aborted(channel, 0xCC); break; - case 0xCD: BX_ERROR(("read cmd 0xCD (CFA WRITE MULTIPLE W/OUT ERASE) not supported")); command_aborted(channel, 0xCD); break; - case 0xD1: BX_ERROR(("read cmd 0xD1 (CHECK MEDIA CARD TYPE) not supported")); command_aborted(channel, 0xD1); break; - case 0xDA: BX_ERROR(("read cmd 0xDA (GET MEDIA STATUS) not supported")); command_aborted(channel, 0xDA); break; - case 0xDE: BX_ERROR(("read cmd 0xDE (MEDIA LOCK) not supported")); command_aborted(channel, 0xDE); break; - case 0xDF: BX_ERROR(("read cmd 0xDF (MEDIA UNLOCK) not supported")); command_aborted(channel, 0xDF); break; - case 0xE0: BX_ERROR(("read cmd 0xE0 (STANDBY IMMEDIATE) not supported")); command_aborted(channel, 0xE0); break; - case 0xE1: BX_ERROR(("read cmd 0xE1 (IDLE IMMEDIATE) not supported")); command_aborted(channel, 0xE1); break; - case 0xE2: BX_ERROR(("read cmd 0xE2 (STANDBY) not supported")); command_aborted(channel, 0xE2); break; - case 0xE3: BX_ERROR(("read cmd 0xE3 (IDLE) not supported")); command_aborted(channel, 0xE3); break; - case 0xE4: BX_ERROR(("read cmd 0xE4 (READ BUFFER) not supported")); command_aborted(channel, 0xE4); break; - case 0xE5: BX_ERROR(("read cmd 0xE5 (CHECK POWER MODE) not supported")); command_aborted(channel, 0xE5); break; - case 0xE6: BX_ERROR(("read cmd 0xE6 (SLEEP) not supported")); command_aborted(channel, 0xE6); break; - case 0xE7: BX_ERROR(("read cmd 0xE7 (FLUSH CACHE) not supported")); command_aborted(channel, 0xE7); break; - case 0xE8: BX_ERROR(("read cmd 0xE8 (WRITE BUFFER) not supported")); command_aborted(channel, 0xE8); break; - case 0xEA: BX_ERROR(("read cmd 0xEA (FLUSH CACHE EXT) not supported")); command_aborted(channel, 0xEA); break; - case 0xED: BX_ERROR(("read cmd 0xED (MEDIA EJECT) not supported")); command_aborted(channel, 0xED); break; - case 0xEF: BX_ERROR(("read cmd 0xEF (SET FEATURES) not supported")); command_aborted(channel, 0xEF); break; - case 0xF1: BX_ERROR(("read cmd 0xF1 (SECURITY SET PASSWORD) not supported")); command_aborted(channel, 0xF1); break; - case 0xF2: BX_ERROR(("read cmd 0xF2 (SECURITY UNLOCK) not supported")); command_aborted(channel, 0xF2); break; - case 0xF3: BX_ERROR(("read cmd 0xF3 (SECURITY ERASE PREPARE) not supported")); command_aborted(channel, 0xF3); break; - case 0xF4: BX_ERROR(("read cmd 0xF4 (SECURITY ERASE UNIT) not supported")); command_aborted(channel, 0xF4); break; - case 0xF5: BX_ERROR(("read cmd 0xF5 (SECURITY FREEZE LOCK) not supported")); command_aborted(channel, 0xF5); break; - case 0xF6: BX_ERROR(("read cmd 0xF6 (SECURITY DISABLE PASSWORD) not supported")); command_aborted(channel, 0xF6); break; - case 0xF8: BX_ERROR(("read cmd 0xF8 (READ NATIVE MAX ADDRESS) not supported")); command_aborted(channel, 0xF8); break; - case 0xF9: BX_ERROR(("read cmd 0xF9 (SET MAX ADDRESS) not supported")); command_aborted(channel, 0xF9); break; - - default: - BX_PANIC(("IO read(0x%04x): current command is %02xh", address, - (unsigned) BX_SELECTED_CONTROLLER(channel).current_command)); - } - break; - - case 0x01: // hard disk error register 0x1f1 - BX_SELECTED_CONTROLLER(channel).status.err = 0; - value8 = (!BX_SELECTED_IS_PRESENT(channel)) ? 0 : BX_SELECTED_CONTROLLER(channel).error_register; - goto return_value8; - break; - case 0x02: // hard disk sector count / interrupt reason 0x1f2 - value8 = (!BX_SELECTED_IS_PRESENT(channel)) ? 0 : BX_SELECTED_CONTROLLER(channel).sector_count; - goto return_value8; - break; - case 0x03: // sector number 0x1f3 - value8 = (!BX_SELECTED_IS_PRESENT(channel)) ? 0 : BX_SELECTED_CONTROLLER(channel).sector_no; - goto return_value8; - case 0x04: // cylinder low 0x1f4 - // -- WARNING : On real hardware the controller registers are shared between drives. - // So we must respond even if the select device is not present. Some OS uses this fact - // to detect the disks.... minix2 for example - value8 = (!BX_ANY_IS_PRESENT(channel)) ? 0 : (BX_SELECTED_CONTROLLER(channel).cylinder_no & 0x00ff); - goto return_value8; - case 0x05: // cylinder high 0x1f5 - // -- WARNING : On real hardware the controller registers are shared between drives. - // So we must respond even if the select device is not present. Some OS uses this fact - // to detect the disks.... minix2 for example - value8 = (!BX_ANY_IS_PRESENT(channel)) ? 0 : BX_SELECTED_CONTROLLER(channel).cylinder_no >> 8; - goto return_value8; - - case 0x06: // hard disk drive and head register 0x1f6 - // b7 Extended data field for ECC - // b6/b5: Used to be sector size. 00=256,01=512,10=1024,11=128 - // Since 512 was always used, bit 6 was taken to mean LBA mode: - // b6 1=LBA mode, 0=CHS mode - // b5 1 - // b4: DRV - // b3..0 HD3..HD0 - value8 = (1 << 7) | - ((BX_SELECTED_CONTROLLER(channel).lba_mode>0) << 6) | - (1 << 5) | // 01b = 512 sector size - (BX_HD_THIS channels[channel].drive_select << 4) | - (BX_SELECTED_CONTROLLER(channel).head_no << 0); - goto return_value8; - break; -//BX_CONTROLLER(channel,0).lba_mode - - case 0x07: // Hard Disk Status 0x1f7 - case 0x16: // Hard Disk Alternate Status 0x3f6 - if (!BX_ANY_IS_PRESENT(channel)) { - // (mch) Just return zero for these registers - value8 = 0; - } else { - value8 = ( - (BX_SELECTED_CONTROLLER(channel).status.busy << 7) | - (BX_SELECTED_CONTROLLER(channel).status.drive_ready << 6) | - (BX_SELECTED_CONTROLLER(channel).status.write_fault << 5) | - (BX_SELECTED_CONTROLLER(channel).status.seek_complete << 4) | - (BX_SELECTED_CONTROLLER(channel).status.drq << 3) | - (BX_SELECTED_CONTROLLER(channel).status.corrected_data << 2) | - (BX_SELECTED_CONTROLLER(channel).status.index_pulse << 1) | - (BX_SELECTED_CONTROLLER(channel).status.err) ); - BX_SELECTED_CONTROLLER(channel).status.index_pulse_count++; - BX_SELECTED_CONTROLLER(channel).status.index_pulse = 0; - if (BX_SELECTED_CONTROLLER(channel).status.index_pulse_count >= INDEX_PULSE_CYCLE) { - BX_SELECTED_CONTROLLER(channel).status.index_pulse = 1; - BX_SELECTED_CONTROLLER(channel).status.index_pulse_count = 0; - } - } - if (port == 0x07) { - DEV_pic_lower_irq(BX_HD_THIS channels[channel].irq); - } - goto return_value8; - break; - - case 0x17: // Hard Disk Address Register 0x3f7 - // Obsolete and unsupported register. Not driven by hard - // disk controller. Report all 1's. If floppy controller - // is handling this address, it will call this function - // set/clear D7 (the only bit it handles), then return - // the combined value - value8 = 0xff; - goto return_value8; - break; - - default: - BX_PANIC(("hard drive: io read to address %x unsupported", - (unsigned) address)); - } - - BX_PANIC(("hard drive: shouldnt get here!")); - return(0); - - return_value32: - BX_DEBUG(("32-bit read from %04x = %08x {%s}", - (unsigned) address, value32, BX_SELECTED_TYPE_STRING(channel))); - return value32; - - return_value16: - BX_DEBUG(("16-bit read from %04x = %04x {%s}", - (unsigned) address, value16, BX_SELECTED_TYPE_STRING(channel))); - return value16; - - return_value8: - BX_DEBUG(("8-bit read from %04x = %02x {%s}", - (unsigned) address, value8, BX_SELECTED_TYPE_STRING(channel))); - return value8; -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_hard_drive_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_HD_SMF - bx_hard_drive_c *class_ptr = (bx_hard_drive_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - - void -bx_hard_drive_c::write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_HD_SMF - off_t logical_sector; - off_t ret; - bx_bool prev_control_reset; - - Bit8u channel = BX_MAX_ATA_CHANNEL; - Bit32u port = 0xff; // undefined - - for (channel=0; channel= 512) - BX_PANIC(("IO write(0x%04x): buffer_index >= 512", address)); - -#if BX_SupportRepeatSpeedups - if (DEV_bulk_io_quantum_requested()) { - unsigned transferLen, quantumsMax; - - quantumsMax = - (512 - BX_SELECTED_CONTROLLER(channel).buffer_index) / io_len; - if ( quantumsMax == 0) - BX_PANIC(("IO write(0x%04x): not enough space for write", address)); - DEV_bulk_io_quantum_transferred() = - DEV_bulk_io_quantum_requested(); - if (quantumsMax < DEV_bulk_io_quantum_transferred()) - DEV_bulk_io_quantum_transferred() = quantumsMax; - transferLen = io_len * DEV_bulk_io_quantum_transferred(); - memcpy( - &BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index], - (Bit8u*) DEV_bulk_io_host_addr(), - transferLen); - DEV_bulk_io_host_addr() += transferLen; - BX_SELECTED_CONTROLLER(channel).buffer_index += transferLen; - } - else -#endif - { - switch(io_len){ - case 4: - BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+3] = (Bit8u)(value >> 24); - BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+2] = (Bit8u)(value >> 16); - case 2: - BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+1] = (Bit8u)(value >> 8); - BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index] = (Bit8u) value; - } - BX_SELECTED_CONTROLLER(channel).buffer_index += io_len; - } - - /* if buffer completely writtten */ - if (BX_SELECTED_CONTROLLER(channel).buffer_index >= 512) { - off_t logical_sector; - off_t ret; - -#if TEST_WRITE_BEYOND_END==1 - BX_SELECTED_CONTROLLER(channel).cylinder_no += 100000; -#endif - if (!calculate_logical_address(channel, &logical_sector)) { - BX_ERROR(("write reached invalid sector %lu, aborting", (unsigned long)logical_sector)); - command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command); - return; - } -#if TEST_WRITE_BEYOND_END==2 - logical_sector += 100000; -#endif - ret = BX_SELECTED_DRIVE(channel).hard_drive->lseek(logical_sector * 512, SEEK_SET); - if (ret < 0) { - BX_ERROR(("could not lseek() hard drive image file at byte %lu", (unsigned long)logical_sector * 512)); - command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command); - return; - } - ret = BX_SELECTED_DRIVE(channel).hard_drive->write((bx_ptr_t) BX_SELECTED_CONTROLLER(channel).buffer, 512); - if (ret < 512) { - BX_ERROR(("could not write() hard drive image file at byte %lu", (unsigned long)logical_sector*512)); - command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command); - return; - } - - BX_SELECTED_CONTROLLER(channel).buffer_index = 0; - - /* update sector count, sector number, cylinder, - * drive, head, status - * if there are more sectors, read next one in... - */ - - increment_address(channel); - - /* When the write is complete, controller clears the DRQ bit and - * sets the BSY bit. - * If at least one more sector is to be written, controller sets DRQ bit, - * clears BSY bit, and issues IRQ - */ - - if (BX_SELECTED_CONTROLLER(channel).sector_count!=0) { - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.drq = 1; - BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - } - else { /* no more sectors to write */ - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; - } - raise_interrupt(channel); - } - break; - - case 0xa0: // PACKET - if (BX_SELECTED_CONTROLLER(channel).buffer_index >= PACKET_SIZE) - BX_PANIC(("IO write(0x%04x): buffer_index >= PACKET_SIZE", address)); - BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index] = value; - BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+1] = (value >> 8); - BX_SELECTED_CONTROLLER(channel).buffer_index += 2; - - /* if packet completely writtten */ - if (BX_SELECTED_CONTROLLER(channel).buffer_index >= PACKET_SIZE) { - // complete command received - Bit8u atapi_command = BX_SELECTED_CONTROLLER(channel).buffer[0]; - - if (bx_dbg.cdrom) - BX_INFO(("cdrom: ATAPI command 0x%x started", atapi_command)); - - switch (atapi_command) { - case 0x00: // test unit ready - if (BX_SELECTED_DRIVE(channel).cdrom.ready) { - atapi_cmd_nop(channel); - } else { - atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - } - raise_interrupt(channel); - break; - - case 0x03: { // request sense - int alloc_length = BX_SELECTED_CONTROLLER(channel).buffer[4]; - init_send_atapi_command(channel, atapi_command, 18, alloc_length); - - // sense data - BX_SELECTED_CONTROLLER(channel).buffer[0] = 0x70 | (1 << 7); - BX_SELECTED_CONTROLLER(channel).buffer[1] = 0; - BX_SELECTED_CONTROLLER(channel).buffer[2] = BX_SELECTED_DRIVE(channel).sense.sense_key; - BX_SELECTED_CONTROLLER(channel).buffer[3] = BX_SELECTED_DRIVE(channel).sense.information.arr[0]; - BX_SELECTED_CONTROLLER(channel).buffer[4] = BX_SELECTED_DRIVE(channel).sense.information.arr[1]; - BX_SELECTED_CONTROLLER(channel).buffer[5] = BX_SELECTED_DRIVE(channel).sense.information.arr[2]; - BX_SELECTED_CONTROLLER(channel).buffer[6] = BX_SELECTED_DRIVE(channel).sense.information.arr[3]; - BX_SELECTED_CONTROLLER(channel).buffer[7] = 17-7; - BX_SELECTED_CONTROLLER(channel).buffer[8] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[0]; - BX_SELECTED_CONTROLLER(channel).buffer[9] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[1]; - BX_SELECTED_CONTROLLER(channel).buffer[10] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[2]; - BX_SELECTED_CONTROLLER(channel).buffer[11] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[3]; - BX_SELECTED_CONTROLLER(channel).buffer[12] = BX_SELECTED_DRIVE(channel).sense.asc; - BX_SELECTED_CONTROLLER(channel).buffer[13] = BX_SELECTED_DRIVE(channel).sense.ascq; - BX_SELECTED_CONTROLLER(channel).buffer[14] = BX_SELECTED_DRIVE(channel).sense.fruc; - BX_SELECTED_CONTROLLER(channel).buffer[15] = BX_SELECTED_DRIVE(channel).sense.key_spec.arr[0]; - BX_SELECTED_CONTROLLER(channel).buffer[16] = BX_SELECTED_DRIVE(channel).sense.key_spec.arr[1]; - BX_SELECTED_CONTROLLER(channel).buffer[17] = BX_SELECTED_DRIVE(channel).sense.key_spec.arr[2]; - - ready_to_send_atapi(channel); - } - break; - - case 0x1b: { // start stop unit - //bx_bool Immed = (BX_SELECTED_CONTROLLER(channel).buffer[1] >> 0) & 1; - bx_bool LoEj = (BX_SELECTED_CONTROLLER(channel).buffer[4] >> 1) & 1; - bx_bool Start = (BX_SELECTED_CONTROLLER(channel).buffer[4] >> 0) & 1; - - if (!LoEj && !Start) { // stop the disc - BX_ERROR(("FIXME: Stop disc not implemented")); - atapi_cmd_nop(channel); - raise_interrupt(channel); - } else if (!LoEj && Start) { // start (spin up) the disc -#ifdef LOWLEVEL_CDROM - BX_SELECTED_DRIVE(channel).cdrom.cd->start_cdrom(); -#endif - BX_ERROR(("FIXME: ATAPI start disc not reading TOC")); - atapi_cmd_nop(channel); - raise_interrupt(channel); - } else if (LoEj && !Start) { // Eject the disc - atapi_cmd_nop(channel); - - if (BX_SELECTED_DRIVE(channel).cdrom.ready) { -#ifdef LOWLEVEL_CDROM - BX_SELECTED_DRIVE(channel).cdrom.cd->eject_cdrom(); -#endif - BX_SELECTED_DRIVE(channel).cdrom.ready = 0; - bx_options.atadevice[channel][BX_SLAVE_SELECTED(channel)].Ostatus->set(BX_EJECTED); - bx_gui->update_drive_status_buttons(); - } - raise_interrupt(channel); - } else { // Load the disc - // My guess is that this command only closes the tray, that's a no-op for us - atapi_cmd_nop(channel); - raise_interrupt(channel); - } - } - break; - - case 0xbd: { // mechanism status - uint16 alloc_length = read_16bit(BX_SELECTED_CONTROLLER(channel).buffer + 8); - - if (alloc_length == 0) - BX_PANIC(("Zero allocation length to MECHANISM STATUS not impl.")); - - init_send_atapi_command(channel, atapi_command, 8, alloc_length); - - BX_SELECTED_CONTROLLER(channel).buffer[0] = 0; // reserved for non changers - BX_SELECTED_CONTROLLER(channel).buffer[1] = 0; // reserved for non changers - - BX_SELECTED_CONTROLLER(channel).buffer[2] = 0; // Current LBA (TODO!) - BX_SELECTED_CONTROLLER(channel).buffer[3] = 0; // Current LBA (TODO!) - BX_SELECTED_CONTROLLER(channel).buffer[4] = 0; // Current LBA (TODO!) - - BX_SELECTED_CONTROLLER(channel).buffer[5] = 1; // one slot - - BX_SELECTED_CONTROLLER(channel).buffer[6] = 0; // slot table length - BX_SELECTED_CONTROLLER(channel).buffer[7] = 0; // slot table length - - ready_to_send_atapi(channel); - } - break; - - case 0x5a: { // mode sense - uint16 alloc_length = read_16bit(BX_SELECTED_CONTROLLER(channel).buffer + 7); - - Bit8u PC = BX_SELECTED_CONTROLLER(channel).buffer[2] >> 6; - Bit8u PageCode = BX_SELECTED_CONTROLLER(channel).buffer[2] & 0x3f; - - switch (PC) { - case 0x0: // current values - switch (PageCode) { - case 0x01: // error recovery - init_send_atapi_command(channel, atapi_command, sizeof(error_recovery_t) + 8, alloc_length); - - init_mode_sense_single(channel, &BX_SELECTED_DRIVE(channel).cdrom.current.error_recovery, - sizeof(error_recovery_t)); - ready_to_send_atapi(channel); - break; - - case 0x2a: // CD-ROM capabilities & mech. status - init_send_atapi_command(channel, atapi_command, 28, alloc_length); - init_mode_sense_single(channel, &BX_SELECTED_CONTROLLER(channel).buffer[8], 28); - BX_SELECTED_CONTROLLER(channel).buffer[8] = 0x2a; - BX_SELECTED_CONTROLLER(channel).buffer[9] = 0x12; - BX_SELECTED_CONTROLLER(channel).buffer[10] = 0x00; - BX_SELECTED_CONTROLLER(channel).buffer[11] = 0x00; - // Multisession, Mode 2 Form 2, Mode 2 Form 1 - BX_SELECTED_CONTROLLER(channel).buffer[12] = 0x70; - BX_SELECTED_CONTROLLER(channel).buffer[13] = (3 << 5); - BX_SELECTED_CONTROLLER(channel).buffer[14] = (unsigned char) -(1 | - (BX_SELECTED_DRIVE(channel).cdrom.locked ? (1 << 1) : 0) | - (1 << 3) | - (1 << 5)); - BX_SELECTED_CONTROLLER(channel).buffer[15] = 0x00; - BX_SELECTED_CONTROLLER(channel).buffer[16] = (706 >> 8) & 0xff; - BX_SELECTED_CONTROLLER(channel).buffer[17] = 706 & 0xff; - BX_SELECTED_CONTROLLER(channel).buffer[18] = 0; - BX_SELECTED_CONTROLLER(channel).buffer[19] = 2; - BX_SELECTED_CONTROLLER(channel).buffer[20] = (512 >> 8) & 0xff; - BX_SELECTED_CONTROLLER(channel).buffer[21] = 512 & 0xff; - BX_SELECTED_CONTROLLER(channel).buffer[22] = (706 >> 8) & 0xff; - BX_SELECTED_CONTROLLER(channel).buffer[23] = 706 & 0xff; - BX_SELECTED_CONTROLLER(channel).buffer[24] = 0; - BX_SELECTED_CONTROLLER(channel).buffer[25] = 0; - BX_SELECTED_CONTROLLER(channel).buffer[26] = 0; - BX_SELECTED_CONTROLLER(channel).buffer[27] = 0; - ready_to_send_atapi(channel); - break; - - case 0x0d: // CD-ROM - case 0x0e: // CD-ROM audio control - case 0x3f: // all - BX_ERROR(("cdrom: MODE SENSE (curr), code=%x" - " not implemented yet", - PageCode)); - atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(channel); - break; - - default: - // not implemeted by this device - BX_INFO(("cdrom: MODE SENSE PC=%x, PageCode=%x," - " not implemented by device", - PC, PageCode)); - atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(channel); - break; - } - break; - - case 0x1: // changeable values - switch (PageCode) { - case 0x01: // error recovery - case 0x0d: // CD-ROM - case 0x0e: // CD-ROM audio control - case 0x2a: // CD-ROM capabilities & mech. status - case 0x3f: // all - BX_ERROR(("cdrom: MODE SENSE (chg), code=%x" - " not implemented yet", - PageCode)); - atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(channel); - break; - - default: - // not implemeted by this device - BX_INFO(("cdrom: MODE SENSE PC=%x, PageCode=%x," - " not implemented by device", - PC, PageCode)); - atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(channel); - break; - } - break; - - case 0x2: // default values - switch (PageCode) { - case 0x01: // error recovery - case 0x0d: // CD-ROM - case 0x0e: // CD-ROM audio control - case 0x2a: // CD-ROM capabilities & mech. status - case 0x3f: // all - BX_PANIC(("cdrom: MODE SENSE (dflt), code=%x", - PageCode)); - break; - - default: - // not implemeted by this device - BX_INFO(("cdrom: MODE SENSE PC=%x, PageCode=%x," - " not implemented by device", - PC, PageCode)); - atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(channel); - break; - } - break; - - case 0x3: // saved values not implemented - atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_SAVING_PARAMETERS_NOT_SUPPORTED); - raise_interrupt(channel); - break; - - default: - BX_PANIC(("Should not get here!")); - break; - } - } - break; - - case 0x12: { // inquiry - uint8 alloc_length = BX_SELECTED_CONTROLLER(channel).buffer[4]; - - init_send_atapi_command(channel, atapi_command, 36, alloc_length); - - BX_SELECTED_CONTROLLER(channel).buffer[0] = 0x05; // CD-ROM - BX_SELECTED_CONTROLLER(channel).buffer[1] = 0x80; // Removable - BX_SELECTED_CONTROLLER(channel).buffer[2] = 0x00; // ISO, ECMA, ANSI version - BX_SELECTED_CONTROLLER(channel).buffer[3] = 0x21; // ATAPI-2, as specified - BX_SELECTED_CONTROLLER(channel).buffer[4] = 31; // additional length (total 36) - BX_SELECTED_CONTROLLER(channel).buffer[5] = 0x00; // reserved - BX_SELECTED_CONTROLLER(channel).buffer[6] = 0x00; // reserved - BX_SELECTED_CONTROLLER(channel).buffer[7] = 0x00; // reserved - - // Vendor ID - const char* vendor_id = "VTAB "; - int i; - for (i = 0; i < 8; i++) - BX_SELECTED_CONTROLLER(channel).buffer[8+i] = vendor_id[i]; - - // Product ID - const char* product_id = "Turbo CD-ROM "; - for (i = 0; i < 16; i++) - BX_SELECTED_CONTROLLER(channel).buffer[16+i] = product_id[i]; - - // Product Revision level - const char* rev_level = "1.0 "; - for (i = 0; i < 4; i++) - BX_SELECTED_CONTROLLER(channel).buffer[32+i] = rev_level[i]; - - ready_to_send_atapi(channel); - } - break; - - case 0x25: { // read cd-rom capacity - // no allocation length??? - init_send_atapi_command(channel, atapi_command, 8, 8); - - if (BX_SELECTED_DRIVE(channel).cdrom.ready) { - uint32 capacity = BX_SELECTED_DRIVE(channel).cdrom.capacity; - BX_INFO(("Capacity is %d sectors (%d bytes)", capacity, capacity * 2048)); - BX_SELECTED_CONTROLLER(channel).buffer[0] = (capacity >> 24) & 0xff; - BX_SELECTED_CONTROLLER(channel).buffer[1] = (capacity >> 16) & 0xff; - BX_SELECTED_CONTROLLER(channel).buffer[2] = (capacity >> 8) & 0xff; - BX_SELECTED_CONTROLLER(channel).buffer[3] = (capacity >> 0) & 0xff; - BX_SELECTED_CONTROLLER(channel).buffer[4] = (2048 >> 24) & 0xff; - BX_SELECTED_CONTROLLER(channel).buffer[5] = (2048 >> 16) & 0xff; - BX_SELECTED_CONTROLLER(channel).buffer[6] = (2048 >> 8) & 0xff; - BX_SELECTED_CONTROLLER(channel).buffer[7] = (2048 >> 0) & 0xff; - ready_to_send_atapi(channel); - } else { - atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - raise_interrupt(channel); - } - } - break; - - case 0xbe: { // read cd - if (BX_SELECTED_DRIVE(channel).cdrom.ready) { - BX_ERROR(("Read CD with CD present not implemented")); - atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(channel); - } else { - atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - raise_interrupt(channel); - } - } - break; - - case 0x43: { // read toc - if (BX_SELECTED_DRIVE(channel).cdrom.ready) { -#ifdef LOWLEVEL_CDROM - bool msf = (BX_SELECTED_CONTROLLER(channel).buffer[1] >> 1) & 1; - uint8 starting_track = BX_SELECTED_CONTROLLER(channel).buffer[6]; -#endif - uint16 alloc_length = read_16bit(BX_SELECTED_CONTROLLER(channel).buffer + 7); - - uint8 format = (BX_SELECTED_CONTROLLER(channel).buffer[9] >> 6); - int i; - switch (format) { - case 0: -#ifdef LOWLEVEL_CDROM - int toc_length; - if (!(BX_SELECTED_DRIVE(channel).cdrom.cd->read_toc(BX_SELECTED_CONTROLLER(channel).buffer, - &toc_length, msf, starting_track))) { - atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(channel); - } else { - init_send_atapi_command(channel, atapi_command, toc_length, alloc_length); - ready_to_send_atapi(channel); - } -#else - BX_PANIC(("LOWLEVEL_CDROM not defined")); -#endif - break; - - case 1: - // multi session stuff. we ignore this and emulate a single session only - init_send_atapi_command(channel, atapi_command, 12, alloc_length); - - BX_SELECTED_CONTROLLER(channel).buffer[0] = 0; - BX_SELECTED_CONTROLLER(channel).buffer[1] = 0x0a; - BX_SELECTED_CONTROLLER(channel).buffer[2] = 1; - BX_SELECTED_CONTROLLER(channel).buffer[3] = 1; - for (i = 0; i < 8; i++) - BX_SELECTED_CONTROLLER(channel).buffer[4+i] = 0; - - ready_to_send_atapi(channel); - break; - - case 2: - default: - BX_PANIC(("(READ TOC) Format %d not supported", format)); - break; - } - } else { - atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - raise_interrupt(channel); - } - } - break; - - case 0x28: // read (10) - case 0xa8: // read (12) - { - - uint32 transfer_length; - if (atapi_command == 0x28) - transfer_length = read_16bit(BX_SELECTED_CONTROLLER(channel).buffer + 7); - else - transfer_length = read_32bit(BX_SELECTED_CONTROLLER(channel).buffer + 6); - - uint32 lba = read_32bit(BX_SELECTED_CONTROLLER(channel).buffer + 2); - - if (!BX_SELECTED_DRIVE(channel).cdrom.ready) { - atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - raise_interrupt(channel); - break; - } - - if (transfer_length == 0) { - atapi_cmd_nop(channel); - raise_interrupt(channel); - BX_INFO(("READ(%d) with transfer length 0, ok", atapi_command==0x28?10:12)); - break; - } - - if (lba + transfer_length > BX_SELECTED_DRIVE(channel).cdrom.capacity) { - atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); - raise_interrupt(channel); - break; - } - - BX_DEBUG(("cdrom: READ (%d) LBA=%d LEN=%d", atapi_command==0x28?10:12, lba, transfer_length)); - - // handle command - init_send_atapi_command(channel, atapi_command, transfer_length * 2048, - transfer_length * 2048, true); - BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks = transfer_length; - BX_SELECTED_DRIVE(channel).cdrom.next_lba = lba; - ready_to_send_atapi(channel); - } - break; - - case 0x2b: { // seek - uint32 lba = read_32bit(BX_SELECTED_CONTROLLER(channel).buffer + 2); - if (!BX_SELECTED_DRIVE(channel).cdrom.ready) { - atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - raise_interrupt(channel); - break; - } - - if (lba > BX_SELECTED_DRIVE(channel).cdrom.capacity) { - atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR); - raise_interrupt(channel); - break; - } - BX_INFO(("cdrom: SEEK (ignored)")); - atapi_cmd_nop(channel); - raise_interrupt(channel); - } - break; - - case 0x1e: { // prevent/allow medium removal - if (BX_SELECTED_DRIVE(channel).cdrom.ready) { - BX_SELECTED_DRIVE(channel).cdrom.locked = BX_SELECTED_CONTROLLER(channel).buffer[4] & 1; - atapi_cmd_nop(channel); - } else { - atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - } - raise_interrupt(channel); - } - break; - - case 0x42: { // read sub-channel - bool msf = get_packet_field(channel,1, 1, 1); - bool sub_q = get_packet_field(channel,2, 6, 1); - uint8 data_format = get_packet_byte(channel,3); - uint8 track_number = get_packet_byte(channel,6); - uint16 alloc_length = get_packet_word(channel,7); - UNUSED(msf); - UNUSED(data_format); - UNUSED(track_number); - - if (!BX_SELECTED_DRIVE(channel).cdrom.ready) { - atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT); - raise_interrupt(channel); - } else { - BX_SELECTED_CONTROLLER(channel).buffer[0] = 0; - BX_SELECTED_CONTROLLER(channel).buffer[1] = 0; // audio not supported - BX_SELECTED_CONTROLLER(channel).buffer[2] = 0; - BX_SELECTED_CONTROLLER(channel).buffer[3] = 0; - - int ret_len = 4; // header size - - if (sub_q) { // !sub_q == header only - BX_ERROR(("Read sub-channel with SubQ not implemented")); - atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, - ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(channel); - } - - init_send_atapi_command(channel, atapi_command, ret_len, alloc_length); - ready_to_send_atapi(channel); - } - } - break; - - case 0x51: { // read disc info - // no-op to keep the Linux CD-ROM driver happy - atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(channel); - } - break; - - case 0x55: // mode select - case 0xa6: // load/unload cd - case 0x4b: // pause/resume - case 0x45: // play audio - case 0x47: // play audio msf - case 0xbc: // play cd - case 0xb9: // read cd msf - case 0x44: // read header - case 0xba: // scan - case 0xbb: // set cd speed - case 0x4e: // stop play/scan - case 0x46: // ??? - case 0x4a: // ??? - BX_ERROR(("ATAPI command 0x%x not implemented yet", - atapi_command)); - atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(channel); - break; - default: - BX_PANIC(("Unknown ATAPI command 0x%x (%d)", - atapi_command, atapi_command)); - // We'd better signal the error if the user chose to continue - atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET); - raise_interrupt(channel); - break; - } - } - - break; - - default: - BX_PANIC(("IO write(0x%04x): current command is %02xh", address, - (unsigned) BX_SELECTED_CONTROLLER(channel).current_command)); - } - break; - - case 0x01: // hard disk write precompensation 0x1f1 - WRITE_FEATURES(channel,value); - if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) { - if (value == 0xff) - BX_INFO(("no precompensation {%s}", BX_SELECTED_TYPE_STRING(channel))); - else - BX_INFO(("precompensation value %02x {%s}", (unsigned) value, BX_SELECTED_TYPE_STRING(channel))); - } - break; - - case 0x02: // hard disk sector count 0x1f2 - WRITE_SECTOR_COUNT(channel,value); - if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) - BX_INFO(("sector count = %u {%s}", (unsigned) value, BX_SELECTED_TYPE_STRING(channel))); - break; - - case 0x03: // hard disk sector number 0x1f3 - WRITE_SECTOR_NUMBER(channel,value); - if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) - BX_INFO(("sector number = %u {%s}", (unsigned) value, BX_SELECTED_TYPE_STRING(channel))); - break; - - case 0x04: // hard disk cylinder low 0x1f4 - WRITE_CYLINDER_LOW(channel,value); - if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) - BX_INFO(("cylinder low = %02xh {%s}", (unsigned) value, BX_SELECTED_TYPE_STRING(channel))); - break; - - case 0x05: // hard disk cylinder high 0x1f5 - WRITE_CYLINDER_HIGH(channel,value); - if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) - BX_INFO(("cylinder high = %02xh {%s}", (unsigned) value, BX_SELECTED_TYPE_STRING(channel))); - break; - - case 0x06: // hard disk drive and head register 0x1f6 - // b7 Extended data field for ECC - // b6/b5: Used to be sector size. 00=256,01=512,10=1024,11=128 - // Since 512 was always used, bit 6 was taken to mean LBA mode: - // b6 1=LBA mode, 0=CHS mode - // b5 1 - // b4: DRV - // b3..0 HD3..HD0 - { - if ( (value & 0xa0) != 0xa0 ) // 1x1xxxxx - BX_INFO(("IO write 0x%04x (%02x): not 1x1xxxxxb", address, (unsigned) value)); - Bit32u drvsel = BX_HD_THIS channels[channel].drive_select = (value >> 4) & 0x01; - WRITE_HEAD_NO(channel,value & 0xf); - if (BX_SELECTED_CONTROLLER(channel).lba_mode == 0 && ((value >> 6) & 1) == 1) - BX_DEBUG(("enabling LBA mode")); - WRITE_LBA_MODE(channel,(value >> 6) & 1); - if (!BX_SELECTED_IS_PRESENT(channel)) { - BX_ERROR (("device set to %d which does not exist",drvsel)); - BX_SELECTED_CONTROLLER(channel).error_register = 0x04; // aborted - BX_SELECTED_CONTROLLER(channel).status.err = 1; - } - break; - } - - case 0x07: // hard disk command 0x1f7 - // (mch) Writes to the command register with drive_select != 0 - // are ignored if no secondary device is present - if ((BX_SLAVE_SELECTED(channel)) && (!BX_SLAVE_IS_PRESENT(channel))) - break; - // Writes to the command register clear the IRQ - DEV_pic_lower_irq(BX_HD_THIS channels[channel].irq); - - if (BX_SELECTED_CONTROLLER(channel).status.busy) - BX_PANIC(("hard disk: command sent, controller BUSY")); - if ( (value & 0xf0) == 0x10 ) - value = 0x10; - switch (value) { - - case 0x10: // CALIBRATE DRIVE - if (!BX_SELECTED_IS_HD(channel)) - BX_PANIC(("calibrate drive issued to non-disk")); - if (!BX_SELECTED_IS_PRESENT(channel)) { - BX_SELECTED_CONTROLLER(channel).error_register = 0x02; // Track 0 not found - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.seek_complete = 0; - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 1; - raise_interrupt(channel); - BX_INFO(("calibrate drive: disk ata%d-%d not present", channel, BX_SLAVE_SELECTED(channel))); - break; - } - - /* move head to cylinder 0, issue IRQ */ - BX_SELECTED_CONTROLLER(channel).error_register = 0; - BX_SELECTED_CONTROLLER(channel).cylinder_no = 0; - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - raise_interrupt(channel); - break; - - case 0x20: // READ MULTIPLE SECTORS, with retries - case 0x21: // READ MULTIPLE SECTORS, without retries - /* update sector_no, always points to current sector - * after each sector is read to buffer, DRQ bit set and issue IRQ - * if interrupt handler transfers all data words into main memory, - * and more sectors to read, then set BSY bit again, clear DRQ and - * read next sector into buffer - * sector count of 0 means 256 sectors - */ - - if (!BX_SELECTED_IS_HD(channel)) { - BX_ERROR(("read multiple issued to non-disk")); - command_aborted(channel, value); - break; - } - - BX_SELECTED_CONTROLLER(channel).current_command = value; - - // Lose98 accesses 0/0/0 in CHS mode - if (!BX_SELECTED_CONTROLLER(channel).lba_mode && - !BX_SELECTED_CONTROLLER(channel).head_no && - !BX_SELECTED_CONTROLLER(channel).cylinder_no && - !BX_SELECTED_CONTROLLER(channel).sector_no) { - BX_INFO(("Read from 0/0/0, aborting command")); - command_aborted(channel, value); - break; - } - -#if TEST_READ_BEYOND_END==2 - BX_SELECTED_CONTROLLER(channel).cylinder_no += 100000; -#endif - if (!calculate_logical_address(channel, &logical_sector)) { - BX_ERROR(("initial read from sector %lu out of bounds, aborting", (unsigned long)logical_sector)); - command_aborted(channel, value); - break; - } -#if TEST_READ_BEYOND_END==3 - logical_sector += 100000; -#endif - ret=BX_SELECTED_DRIVE(channel).hard_drive->lseek(logical_sector * 512, SEEK_SET); - if (ret < 0) { - BX_ERROR (("could not lseek() hard drive image file, aborting")); - command_aborted(channel, value); - break; - } - ret = BX_SELECTED_DRIVE(channel).hard_drive->read((bx_ptr_t) BX_SELECTED_CONTROLLER(channel).buffer, 512); - if (ret < 512) { - BX_ERROR(("logical sector was %lu", (unsigned long)logical_sector)); - BX_ERROR(("could not read() hard drive image file at byte %lu", (unsigned long)logical_sector*512)); - command_aborted(channel, value); - break; - } - - BX_SELECTED_CONTROLLER(channel).error_register = 0; - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; - BX_SELECTED_CONTROLLER(channel).status.drq = 1; - BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - BX_SELECTED_CONTROLLER(channel).buffer_index = 0; - raise_interrupt(channel); - break; - - case 0x30: /* WRITE SECTORS, with retries */ - /* update sector_no, always points to current sector - * after each sector is read to buffer, DRQ bit set and issue IRQ - * if interrupt handler transfers all data words into main memory, - * and more sectors to read, then set BSY bit again, clear DRQ and - * read next sector into buffer - * sector count of 0 means 256 sectors - */ - - if (!BX_SELECTED_IS_HD(channel)) - BX_PANIC(("write multiple issued to non-disk")); - - if (BX_SELECTED_CONTROLLER(channel).status.busy) { - BX_PANIC(("write command: BSY bit set")); - } - BX_SELECTED_CONTROLLER(channel).current_command = value; - - // implicit seek done :^) - BX_SELECTED_CONTROLLER(channel).error_register = 0; - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - // BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; - BX_SELECTED_CONTROLLER(channel).status.drq = 1; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - BX_SELECTED_CONTROLLER(channel).buffer_index = 0; - break; - - case 0x90: // EXECUTE DEVICE DIAGNOSTIC - if (BX_SELECTED_CONTROLLER(channel).status.busy) { - BX_PANIC(("diagnostic command: BSY bit set")); - } - if (!BX_SELECTED_IS_HD(channel)) - BX_PANIC(("drive diagnostics issued to non-disk")); - BX_SELECTED_CONTROLLER(channel).error_register = 0x81; // Drive 1 failed, no error on drive 0 - // BX_SELECTED_CONTROLLER(channel).status.busy = 0; // not needed - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - break; - - case 0x91: // INITIALIZE DRIVE PARAMETERS - if (BX_SELECTED_CONTROLLER(channel).status.busy) { - BX_PANIC(("init drive parameters command: BSY bit set")); - } - if (!BX_SELECTED_IS_HD(channel)) - BX_PANIC(("initialize drive parameters issued to non-disk")); - // sets logical geometry of specified drive - BX_DEBUG(("init drive params: sec=%u, drive sel=%u, head=%u", - (unsigned) BX_SELECTED_CONTROLLER(channel).sector_count, - (unsigned) BX_HD_THIS channels[channel].drive_select, - (unsigned) BX_SELECTED_CONTROLLER(channel).head_no)); - if (!BX_SELECTED_IS_PRESENT(channel)) { - BX_PANIC(("init drive params: disk ata%d-%d not present", channel, BX_SLAVE_SELECTED(channel))); - //BX_SELECTED_CONTROLLER(channel).error_register = 0x12; - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - raise_interrupt(channel); - break; - } - if (BX_SELECTED_CONTROLLER(channel).sector_count != BX_SELECTED_DRIVE(channel).hard_drive->sectors) - BX_PANIC(("init drive params: sector count doesnt match %d!=%d", BX_SELECTED_CONTROLLER(channel).sector_count, BX_SELECTED_DRIVE(channel).hard_drive->sectors)); - if ( BX_SELECTED_CONTROLLER(channel).head_no != (BX_SELECTED_DRIVE(channel).hard_drive->heads-1) ) - BX_PANIC(("init drive params: head number doesn't match %d != %d",BX_SELECTED_CONTROLLER(channel).head_no, BX_SELECTED_DRIVE(channel).hard_drive->heads-1)); - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - raise_interrupt(channel); - break; - - case 0xec: // IDENTIFY DEVICE - if (bx_options.OnewHardDriveSupport->get ()) { - if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) - BX_INFO(("Drive ID Command issued : 0xec ")); - - if (!BX_SELECTED_IS_PRESENT(channel)) { - BX_INFO(("disk ata%d-%d not present, aborting",channel,BX_SLAVE_SELECTED(channel))); - command_aborted(channel, value); - break; - } - if (BX_SELECTED_IS_CD(channel)) { - BX_SELECTED_CONTROLLER(channel).head_no = 0; - BX_SELECTED_CONTROLLER(channel).sector_count = 1; - BX_SELECTED_CONTROLLER(channel).sector_no = 1; - BX_SELECTED_CONTROLLER(channel).cylinder_no = 0xeb14; - command_aborted(channel, 0xec); - } else { - BX_SELECTED_CONTROLLER(channel).current_command = value; - BX_SELECTED_CONTROLLER(channel).error_register = 0; - - // See ATA/ATAPI-4, 8.12 - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; - BX_SELECTED_CONTROLLER(channel).status.drq = 1; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - - BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; - BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; - - BX_SELECTED_CONTROLLER(channel).buffer_index = 0; - raise_interrupt(channel); - identify_drive(channel); - } - } - else { - BX_INFO(("sent IDENTIFY DEVICE (0xec) to old hard drive")); - command_aborted(channel, value); - } - break; - - case 0xef: // SET FEATURES - switch(BX_SELECTED_CONTROLLER(channel).features) { - case 0x02: // Enable and - case 0x82: // Disable write cache. - case 0xAA: // Enable and - case 0x55: // Disable look-ahead cache. - case 0xCC: // Enable and - case 0x66: // Disable reverting to power-on default - BX_INFO(("SET FEATURES subcommand 0x%02x not supported by disk.", (unsigned) BX_SELECTED_CONTROLLER(channel).features)); - command_aborted(channel, value); - break; - - default: - BX_PANIC(("SET FEATURES with unknown subcommand: 0x%02x", (unsigned) BX_SELECTED_CONTROLLER(channel).features )); - // We'd better signal the error if the user chose to continue - command_aborted(channel, value); - } - break; - - case 0x40: // READ VERIFY SECTORS - if (bx_options.OnewHardDriveSupport->get ()) { - if (!BX_SELECTED_IS_HD(channel)) - BX_PANIC(("read verify issued to non-disk")); - BX_INFO(("Verify Command : 0x40 ! ")); - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - raise_interrupt(channel); - } - else { - BX_INFO(("sent READ VERIFY SECTORS (0x40) to old hard drive")); - command_aborted(channel, value); - } - break; - - case 0xc6: // SET MULTIPLE MODE (mch) - if (BX_SELECTED_CONTROLLER(channel).sector_count != 128 && - BX_SELECTED_CONTROLLER(channel).sector_count != 64 && - BX_SELECTED_CONTROLLER(channel).sector_count != 32 && - BX_SELECTED_CONTROLLER(channel).sector_count != 16 && - BX_SELECTED_CONTROLLER(channel).sector_count != 8 && - BX_SELECTED_CONTROLLER(channel).sector_count != 4 && - BX_SELECTED_CONTROLLER(channel).sector_count != 2) - command_aborted(channel, value); - - if (!BX_SELECTED_IS_HD(channel)) - BX_PANIC(("set multiple mode issued to non-disk")); - - BX_SELECTED_CONTROLLER(channel).sectors_per_block = BX_SELECTED_CONTROLLER(channel).sector_count; - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - break; - - // ATAPI commands - case 0xa1: // IDENTIFY PACKET DEVICE - if (BX_SELECTED_IS_CD(channel)) { - BX_SELECTED_CONTROLLER(channel).current_command = value; - BX_SELECTED_CONTROLLER(channel).error_register = 0; - - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; - BX_SELECTED_CONTROLLER(channel).status.drq = 1; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - - BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; - BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; - - BX_SELECTED_CONTROLLER(channel).buffer_index = 0; - raise_interrupt(channel); - identify_ATAPI_drive(channel); - } else { - command_aborted(channel, 0xa1); - } - break; - - case 0x08: // DEVICE RESET (atapi) - if (BX_SELECTED_IS_CD(channel)) { - BX_SELECTED_CONTROLLER(channel).status.busy = 1; - BX_SELECTED_CONTROLLER(channel).error_register &= ~(1 << 7); - - // device signature - BX_SELECTED_CONTROLLER(channel).head_no = 0; - BX_SELECTED_CONTROLLER(channel).sector_count = 1; - BX_SELECTED_CONTROLLER(channel).sector_no = 1; - BX_SELECTED_CONTROLLER(channel).cylinder_no = 0xeb14; - - BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - - } else { - BX_DEBUG(("ATAPI Device Reset on non-cd device")); - command_aborted(channel, 0x08); - } - break; - - case 0xa0: // SEND PACKET (atapi) - if (BX_SELECTED_IS_CD(channel)) { - // PACKET - if (BX_SELECTED_CONTROLLER(channel).features & (1 << 0)) - BX_PANIC(("PACKET-DMA not supported")); - if (BX_SELECTED_CONTROLLER(channel).features & (1 << 1)) - BX_PANIC(("PACKET-overlapped not supported")); - - // We're already ready! - BX_SELECTED_CONTROLLER(channel).sector_count = 1; - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; - // serv bit?? - BX_SELECTED_CONTROLLER(channel).status.drq = 1; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - - // NOTE: no interrupt here - BX_SELECTED_CONTROLLER(channel).current_command = value; - BX_SELECTED_CONTROLLER(channel).buffer_index = 0; - } else { - command_aborted (channel, 0xa0); - } - break; - - case 0xa2: // SERVICE (atapi), optional - if (BX_SELECTED_IS_CD(channel)) { - BX_PANIC(("ATAPI SERVICE not implemented")); - } else { - command_aborted (channel, 0xa2); - } - break; - - // power management - case 0xe5: // CHECK POWER MODE - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - BX_SELECTED_CONTROLLER(channel).sector_count = 0xff; // Active or Idle mode - raise_interrupt(channel); - break; - - case 0x70: // SEEK (cgs) - if (BX_SELECTED_IS_HD(channel)) { - BX_DEBUG(("write cmd 0x70 (SEEK) executing")); - if (!calculate_logical_address(channel, &logical_sector)) { - BX_ERROR(("initial seek to sector %lu out of bounds, aborting", (unsigned long)logical_sector)); - command_aborted(channel, value); - break; - } - BX_SELECTED_CONTROLLER(channel).error_register = 0; - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1; - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - BX_SELECTED_CONTROLLER(channel).buffer_index = 0; - BX_DEBUG(("s[0].controller.control.disable_irq = %02x", (BX_HD_THIS channels[channel].drives[0]).controller.control.disable_irq)); - BX_DEBUG(("s[1].controller.control.disable_irq = %02x", (BX_HD_THIS channels[channel].drives[1]).controller.control.disable_irq)); - BX_DEBUG(("SEEK completed. error_register = %02x", BX_SELECTED_CONTROLLER(channel).error_register)); - raise_interrupt(channel); - BX_DEBUG(("SEEK interrupt completed")); - } else { - BX_ERROR(("write cmd 0x70 (SEEK) not supported for non-disk")); - command_aborted(channel, 0x70); - } - break; - - - - // List all the write operations that are defined in the ATA/ATAPI spec - // that we don't support. Commands that are listed here will cause a - // BX_ERROR, which is non-fatal, and the command will be aborted. - case 0x22: BX_ERROR(("write cmd 0x22 (READ LONG) not supported")); command_aborted(channel, 0x22); break; - case 0x23: BX_ERROR(("write cmd 0x23 (READ LONG NO RETRY) not supported")); command_aborted(channel, 0x23); break; - case 0x24: BX_ERROR(("write cmd 0x24 (READ SECTORS EXT) not supported"));command_aborted(channel, 0x24); break; - case 0x25: BX_ERROR(("write cmd 0x25 (READ DMA EXT) not supported"));command_aborted(channel, 0x25); break; - case 0x26: BX_ERROR(("write cmd 0x26 (READ DMA QUEUED EXT) not supported"));command_aborted(channel, 0x26); break; - case 0x27: BX_ERROR(("write cmd 0x27 (READ NATIVE MAX ADDRESS EXT) not supported"));command_aborted(channel, 0x27); break; - case 0x29: BX_ERROR(("write cmd 0x29 (READ MULTIPLE EXT) not supported"));command_aborted(channel, 0x29); break; - case 0x2A: BX_ERROR(("write cmd 0x2A (READ STREAM DMA) not supported"));command_aborted(channel, 0x2A); break; - case 0x2B: BX_ERROR(("write cmd 0x2B (READ STREAM PIO) not supported"));command_aborted(channel, 0x2B); break; - case 0x2F: BX_ERROR(("write cmd 0x2F (READ LOG EXT) not supported"));command_aborted(channel, 0x2F); break; - case 0x31: BX_ERROR(("write cmd 0x31 (WRITE SECTORS NO RETRY) not supported")); command_aborted(channel, 0x31); break; - case 0x32: BX_ERROR(("write cmd 0x32 (WRITE LONG) not supported")); command_aborted(channel, 0x32); break; - case 0x33: BX_ERROR(("write cmd 0x33 (WRITE LONG NO RETRY) not supported")); command_aborted(channel, 0x33); break; - case 0x34: BX_ERROR(("write cmd 0x34 (WRITE SECTORS EXT) not supported"));command_aborted(channel, 0x34); break; - case 0x35: BX_ERROR(("write cmd 0x35 (WRITE DMA EXT) not supported"));command_aborted(channel, 0x35); break; - case 0x36: BX_ERROR(("write cmd 0x36 (WRITE DMA QUEUED EXT) not supported"));command_aborted(channel, 0x36); break; - case 0x37: BX_ERROR(("write cmd 0x37 (SET MAX ADDRESS EXT) not supported"));command_aborted(channel, 0x37); break; - case 0x38: BX_ERROR(("write cmd 0x38 (CFA WRITE SECTORS W/OUT ERASE) not supported"));command_aborted(channel, 0x38); break; - case 0x39: BX_ERROR(("write cmd 0x39 (WRITE MULTIPLE EXT) not supported"));command_aborted(channel, 0x39); break; - case 0x3A: BX_ERROR(("write cmd 0x3A (WRITE STREAM DMA) not supported"));command_aborted(channel, 0x3A); break; - case 0x3B: BX_ERROR(("write cmd 0x3B (WRITE STREAM PIO) not supported"));command_aborted(channel, 0x3B); break; - case 0x3F: BX_ERROR(("write cmd 0x3F (WRITE LOG EXT) not supported"));command_aborted(channel, 0x3F); break; - case 0x41: BX_ERROR(("write cmd 0x41 (READ VERIFY SECTORS NO RETRY) not supported")); command_aborted(channel, 0x41); break; - case 0x42: BX_ERROR(("write cmd 0x42 (READ VERIFY SECTORS EXT) not supported"));command_aborted(channel, 0x42); break; - case 0x50: BX_ERROR(("write cmd 0x50 (FORMAT TRACK) not supported")); command_aborted(channel, 0x50); break; - case 0x51: BX_ERROR(("write cmd 0x51 (CONFIGURE STREAM) not supported"));command_aborted(channel, 0x51); break; - case 0x87: BX_ERROR(("write cmd 0x87 (CFA TRANSLATE SECTOR) not supported"));command_aborted(channel, 0x87); break; - case 0x92: BX_ERROR(("write cmd 0x92 (DOWNLOAD MICROCODE) not supported"));command_aborted(channel, 0x92); break; - case 0x94: BX_ERROR(("write cmd 0x94 (STANDBY IMMEDIATE) not supported")); command_aborted(channel, 0x94); break; - case 0x95: BX_ERROR(("write cmd 0x95 (IDLE IMMEDIATE) not supported")); command_aborted(channel, 0x95); break; - case 0x96: BX_ERROR(("write cmd 0x96 (STANDBY) not supported")); command_aborted(channel, 0x96); break; - case 0x97: BX_ERROR(("write cmd 0x97 (IDLE) not supported")); command_aborted(channel, 0x97); break; - case 0x98: BX_ERROR(("write cmd 0x98 (CHECK POWER MODE) not supported")); command_aborted(channel, 0x98); break; - case 0x99: BX_ERROR(("write cmd 0x99 (SLEEP) not supported")); command_aborted(channel, 0x99); break; - case 0xB0: BX_ERROR(("write cmd 0xB0 (SMART commands) not supported"));command_aborted(channel, 0xB0); break; - case 0xB1: BX_ERROR(("write cmd 0xB1 (DEVICE CONFIGURATION commands) not supported"));command_aborted(channel, 0xB1); break; - case 0xC0: BX_ERROR(("write cmd 0xC0 (CFA ERASE SECTORS) not supported"));command_aborted(channel, 0xC0); break; - case 0xC4: BX_ERROR(("write cmd 0xC4 (READ MULTIPLE) not supported"));command_aborted(channel, 0xC4); break; - case 0xC5: BX_ERROR(("write cmd 0xC5 (WRITE MULTIPLE) not supported"));command_aborted(channel, 0xC5); break; - case 0xC7: BX_ERROR(("write cmd 0xC7 (READ DMA QUEUED) not supported"));command_aborted(channel, 0xC7); break; - case 0xC8: BX_ERROR(("write cmd 0xC8 (READ DMA) not supported"));command_aborted(channel, 0xC8); break; - case 0xC9: BX_ERROR(("write cmd 0xC9 (READ DMA NO RETRY) not supported")); command_aborted(channel, 0xC9); break; - case 0xCA: BX_ERROR(("write cmd 0xCA (WRITE DMA) not supported"));command_aborted(channel, 0xCA); break; - case 0xCC: BX_ERROR(("write cmd 0xCC (WRITE DMA QUEUED) not supported"));command_aborted(channel, 0xCC); break; - case 0xCD: BX_ERROR(("write cmd 0xCD (CFA WRITE MULTIPLE W/OUT ERASE) not supported"));command_aborted(channel, 0xCD); break; - case 0xD1: BX_ERROR(("write cmd 0xD1 (CHECK MEDIA CARD TYPE) not supported"));command_aborted(channel, 0xD1); break; - case 0xDA: BX_ERROR(("write cmd 0xDA (GET MEDIA STATUS) not supported"));command_aborted(channel, 0xDA); break; - case 0xDE: BX_ERROR(("write cmd 0xDE (MEDIA LOCK) not supported"));command_aborted(channel, 0xDE); break; - case 0xDF: BX_ERROR(("write cmd 0xDF (MEDIA UNLOCK) not supported"));command_aborted(channel, 0xDF); break; - case 0xE0: BX_ERROR(("write cmd 0xE0 (STANDBY IMMEDIATE) not supported"));command_aborted(channel, 0xE0); break; - case 0xE1: BX_ERROR(("write cmd 0xE1 (IDLE IMMEDIATE) not supported"));command_aborted(channel, 0xE1); break; - case 0xE2: BX_ERROR(("write cmd 0xE2 (STANDBY) not supported"));command_aborted(channel, 0xE2); break; - case 0xE3: BX_ERROR(("write cmd 0xE3 (IDLE) not supported"));command_aborted(channel, 0xE3); break; - case 0xE4: BX_ERROR(("write cmd 0xE4 (READ BUFFER) not supported"));command_aborted(channel, 0xE4); break; - case 0xE6: BX_ERROR(("write cmd 0xE6 (SLEEP) not supported"));command_aborted(channel, 0xE6); break; - case 0xE7: BX_ERROR(("write cmd 0xE7 (FLUSH CACHE) not supported"));command_aborted(channel, 0xE7); break; - case 0xE8: BX_ERROR(("write cmd 0xE8 (WRITE BUFFER) not supported"));command_aborted(channel, 0xE8); break; - case 0xEA: BX_ERROR(("write cmd 0xEA (FLUSH CACHE EXT) not supported"));command_aborted(channel, 0xEA); break; - case 0xED: BX_ERROR(("write cmd 0xED (MEDIA EJECT) not supported"));command_aborted(channel, 0xED); break; - case 0xF1: BX_ERROR(("write cmd 0xF1 (SECURITY SET PASSWORD) not supported"));command_aborted(channel, 0xF1); break; - case 0xF2: BX_ERROR(("write cmd 0xF2 (SECURITY UNLOCK) not supported"));command_aborted(channel, 0xF2); break; - case 0xF3: BX_ERROR(("write cmd 0xF3 (SECURITY ERASE PREPARE) not supported"));command_aborted(channel, 0xF3); break; - case 0xF4: BX_ERROR(("write cmd 0xF4 (SECURITY ERASE UNIT) not supported"));command_aborted(channel, 0xF4); break; - case 0xF5: BX_ERROR(("write cmd 0xF5 (SECURITY FREEZE LOCK) not supported"));command_aborted(channel, 0xF5); break; - case 0xF6: BX_ERROR(("write cmd 0xF6 (SECURITY DISABLE PASSWORD) not supported"));command_aborted(channel, 0xF6); break; - case 0xF8: BX_ERROR(("write cmd 0xF8 (READ NATIVE MAX ADDRESS) not supported"));command_aborted(channel, 0xF8); break; - case 0xF9: BX_ERROR(("write cmd 0xF9 (SET MAX ADDRESS) not supported"));command_aborted(channel, 0xF9); break; - - default: - BX_PANIC(("IO write(0x%04x): command 0x%02x", address, (unsigned) value)); - // if user foolishly decides to continue, abort the command - // so that the software knows the drive didn't understand it. - command_aborted(channel, value); - } - break; - - case 0x16: // hard disk adapter control 0x3f6 - // (mch) Even if device 1 was selected, a write to this register - // goes to device 0 (if device 1 is absent) - - prev_control_reset = BX_SELECTED_CONTROLLER(channel).control.reset; - BX_HD_THIS channels[channel].drives[0].controller.control.reset = value & 0x04; - BX_HD_THIS channels[channel].drives[1].controller.control.reset = value & 0x04; - // CGS: was: BX_SELECTED_CONTROLLER(channel).control.disable_irq = value & 0x02; - BX_HD_THIS channels[channel].drives[0].controller.control.disable_irq = value & 0x02; - BX_HD_THIS channels[channel].drives[1].controller.control.disable_irq = value & 0x02; - - BX_DEBUG(( "adpater control reg: reset controller = %d", - (unsigned) (BX_SELECTED_CONTROLLER(channel).control.reset) ? 1 : 0 )); - BX_DEBUG(( "adpater control reg: disable_irq(X) = %d", - (unsigned) (BX_SELECTED_CONTROLLER(channel).control.disable_irq) ? 1 : 0 )); - - if (!prev_control_reset && BX_SELECTED_CONTROLLER(channel).control.reset) { - // transition from 0 to 1 causes all drives to reset - BX_DEBUG(("hard drive: RESET")); - - // (mch) Set BSY, drive not ready - for (int id = 0; id < 2; id++) { - BX_CONTROLLER(channel,id).status.busy = 1; - BX_CONTROLLER(channel,id).status.drive_ready = 0; - BX_CONTROLLER(channel,id).reset_in_progress = 1; - - BX_CONTROLLER(channel,id).status.write_fault = 0; - BX_CONTROLLER(channel,id).status.seek_complete = 1; - BX_CONTROLLER(channel,id).status.drq = 0; - BX_CONTROLLER(channel,id).status.corrected_data = 0; - BX_CONTROLLER(channel,id).status.err = 0; - - BX_CONTROLLER(channel,id).error_register = 0x01; // diagnostic code: no error - - BX_CONTROLLER(channel,id).current_command = 0x00; - BX_CONTROLLER(channel,id).buffer_index = 0; - - BX_CONTROLLER(channel,id).sectors_per_block = 0x80; - BX_CONTROLLER(channel,id).lba_mode = 0; - - BX_CONTROLLER(channel,id).control.disable_irq = 0; - DEV_pic_lower_irq(BX_HD_THIS channels[channel].irq); - } - } else if (BX_SELECTED_CONTROLLER(channel).reset_in_progress && - !BX_SELECTED_CONTROLLER(channel).control.reset) { - // Clear BSY and DRDY - BX_DEBUG(("Reset complete {%s}", BX_SELECTED_TYPE_STRING(channel))); - for (int id = 0; id < 2; id++) { - BX_CONTROLLER(channel,id).status.busy = 0; - BX_CONTROLLER(channel,id).status.drive_ready = 1; - BX_CONTROLLER(channel,id).reset_in_progress = 0; - - // Device signature - if (BX_DRIVE_IS_HD(channel,id)) { - BX_CONTROLLER(channel,id).head_no = 0; - BX_CONTROLLER(channel,id).sector_count = 1; - BX_CONTROLLER(channel,id).sector_no = 1; - BX_CONTROLLER(channel,id).cylinder_no = 0; - } else { - BX_CONTROLLER(channel,id).head_no = 0; - BX_CONTROLLER(channel,id).sector_count = 1; - BX_CONTROLLER(channel,id).sector_no = 1; - BX_CONTROLLER(channel,id).cylinder_no = 0xeb14; - } - } - } - BX_DEBUG(("s[0].controller.control.disable_irq = %02x", (BX_HD_THIS channels[channel].drives[0]).controller.control.disable_irq)); - BX_DEBUG(("s[1].controller.control.disable_irq = %02x", (BX_HD_THIS channels[channel].drives[1]).controller.control.disable_irq)); - break; - - default: - BX_PANIC(("hard drive: io write to address %x = %02x", - (unsigned) address, (unsigned) value)); - } -} - - void -bx_hard_drive_c::close_harddrive(void) -{ - for (Bit8u channel=0; channelclose(); - if(BX_HD_THIS channels[channel].drives[1].hard_drive != NULL) - BX_HD_THIS channels[channel].drives[1].hard_drive->close(); - } -} - - - bx_bool BX_CPP_AttrRegparmN(2) -bx_hard_drive_c::calculate_logical_address(Bit8u channel, off_t *sector) -{ - off_t logical_sector; - - if (BX_SELECTED_CONTROLLER(channel).lba_mode) { - //bx_printf ("disk: calculate: %d %d %d\n", ((Bit32u)BX_SELECTED_CONTROLLER(channel).head_no), ((Bit32u)BX_SELECTED_CONTROLLER(channel).cylinder_no), (Bit32u)BX_SELECTED_CONTROLLER(channel).sector_no); - logical_sector = ((Bit32u)BX_SELECTED_CONTROLLER(channel).head_no) << 24 | - ((Bit32u)BX_SELECTED_CONTROLLER(channel).cylinder_no) << 8 | - (Bit32u)BX_SELECTED_CONTROLLER(channel).sector_no; - //bx_printf ("disk: result: %u\n", logical_sector); - } else - logical_sector = (BX_SELECTED_CONTROLLER(channel).cylinder_no * BX_SELECTED_DRIVE(channel).hard_drive->heads * - BX_SELECTED_DRIVE(channel).hard_drive->sectors) + - (BX_SELECTED_CONTROLLER(channel).head_no * BX_SELECTED_DRIVE(channel).hard_drive->sectors) + - (BX_SELECTED_CONTROLLER(channel).sector_no - 1); - - Bit32u sector_count= - (Bit32u)BX_SELECTED_DRIVE(channel).hard_drive->cylinders * - (Bit32u)BX_SELECTED_DRIVE(channel).hard_drive->heads * - (Bit32u)BX_SELECTED_DRIVE(channel).hard_drive->sectors; - - if (logical_sector >= sector_count) { - BX_ERROR (("calc_log_addr: out of bounds (%d/%d)", (Bit32u)logical_sector, sector_count)); - return false; - } - *sector = logical_sector; - return true; -} - - void BX_CPP_AttrRegparmN(1) -bx_hard_drive_c::increment_address(Bit8u channel) -{ - BX_SELECTED_CONTROLLER(channel).sector_count--; - - if (BX_SELECTED_CONTROLLER(channel).lba_mode) { - off_t current_address; - calculate_logical_address(channel, ¤t_address); - current_address++; - BX_SELECTED_CONTROLLER(channel).head_no = (Bit8u)((current_address >> 24) & 0xf); - BX_SELECTED_CONTROLLER(channel).cylinder_no = (Bit16u)((current_address >> 8) & 0xffff); - BX_SELECTED_CONTROLLER(channel).sector_no = (Bit8u)((current_address) & 0xff); - } else { - BX_SELECTED_CONTROLLER(channel).sector_no++; - if (BX_SELECTED_CONTROLLER(channel).sector_no > BX_SELECTED_DRIVE(channel).hard_drive->sectors) { - BX_SELECTED_CONTROLLER(channel).sector_no = 1; - BX_SELECTED_CONTROLLER(channel).head_no++; - if (BX_SELECTED_CONTROLLER(channel).head_no >= BX_SELECTED_DRIVE(channel).hard_drive->heads) { - BX_SELECTED_CONTROLLER(channel).head_no = 0; - BX_SELECTED_CONTROLLER(channel).cylinder_no++; - if (BX_SELECTED_CONTROLLER(channel).cylinder_no >= BX_SELECTED_DRIVE(channel).hard_drive->cylinders) - BX_SELECTED_CONTROLLER(channel).cylinder_no = BX_SELECTED_DRIVE(channel).hard_drive->cylinders - 1; - } - } - } -} - - void -bx_hard_drive_c::identify_ATAPI_drive(Bit8u channel) -{ - unsigned i; - - BX_SELECTED_DRIVE(channel).id_drive[0] = (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0); // Removable CDROM, 50us response, 12 byte packets - - for (i = 1; i <= 9; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - const char* serial_number = " VT00001\0\0\0\0\0\0\0\0\0\0\0\0"; - for (i = 0; i < 10; i++) { - BX_SELECTED_DRIVE(channel).id_drive[10+i] = (serial_number[i*2] << 8) | - serial_number[i*2 + 1]; - } - - for (i = 20; i <= 22; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - const char* firmware = "ALPHA1 "; - for (i = 0; i < strlen(firmware)/2; i++) { - BX_SELECTED_DRIVE(channel).id_drive[23+i] = (firmware[i*2] << 8) | - firmware[i*2 + 1]; - } - BX_ASSERT((23+i) == 27); - - for (i = 0; i < strlen((char *) BX_SELECTED_MODEL(channel))/2; i++) { - BX_SELECTED_DRIVE(channel).id_drive[27+i] = (BX_SELECTED_MODEL(channel)[i*2] << 8) | - BX_SELECTED_MODEL(channel)[i*2 + 1]; - } - BX_ASSERT((27+i) == 47); - - BX_SELECTED_DRIVE(channel).id_drive[47] = 0; - BX_SELECTED_DRIVE(channel).id_drive[48] = 1; // 32 bits access - - BX_SELECTED_DRIVE(channel).id_drive[49] = (1 << 9); // LBA supported - - BX_SELECTED_DRIVE(channel).id_drive[50] = 0; - BX_SELECTED_DRIVE(channel).id_drive[51] = 0; - BX_SELECTED_DRIVE(channel).id_drive[52] = 0; - - BX_SELECTED_DRIVE(channel).id_drive[53] = 3; // words 64-70, 54-58 valid - - for (i = 54; i <= 62; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - // copied from CFA540A - BX_SELECTED_DRIVE(channel).id_drive[63] = 0x0103; // variable (DMA stuff) - BX_SELECTED_DRIVE(channel).id_drive[64] = 0x0001; // PIO - BX_SELECTED_DRIVE(channel).id_drive[65] = 0x00b4; - BX_SELECTED_DRIVE(channel).id_drive[66] = 0x00b4; - BX_SELECTED_DRIVE(channel).id_drive[67] = 0x012c; - BX_SELECTED_DRIVE(channel).id_drive[68] = 0x00b4; - - BX_SELECTED_DRIVE(channel).id_drive[69] = 0; - BX_SELECTED_DRIVE(channel).id_drive[70] = 0; - BX_SELECTED_DRIVE(channel).id_drive[71] = 30; // faked - BX_SELECTED_DRIVE(channel).id_drive[72] = 30; // faked - BX_SELECTED_DRIVE(channel).id_drive[73] = 0; - BX_SELECTED_DRIVE(channel).id_drive[74] = 0; - - BX_SELECTED_DRIVE(channel).id_drive[75] = 0; - - for (i = 76; i <= 79; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - BX_SELECTED_DRIVE(channel).id_drive[80] = 0x1e; // supports up to ATA/ATAPI-4 - BX_SELECTED_DRIVE(channel).id_drive[81] = 0; - BX_SELECTED_DRIVE(channel).id_drive[82] = 0; - BX_SELECTED_DRIVE(channel).id_drive[83] = 0; - BX_SELECTED_DRIVE(channel).id_drive[84] = 0; - BX_SELECTED_DRIVE(channel).id_drive[85] = 0; - BX_SELECTED_DRIVE(channel).id_drive[86] = 0; - BX_SELECTED_DRIVE(channel).id_drive[87] = 0; - BX_SELECTED_DRIVE(channel).id_drive[88] = 0; - - for (i = 89; i <= 126; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - BX_SELECTED_DRIVE(channel).id_drive[127] = 0; - BX_SELECTED_DRIVE(channel).id_drive[128] = 0; - - for (i = 129; i <= 159; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - for (i = 160; i <= 255; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - // now convert the id_drive array (native 256 word format) to - // the controller buffer (512 bytes) - Bit16u temp16; - for (i = 0; i <= 255; i++) { - temp16 = BX_SELECTED_DRIVE(channel).id_drive[i]; - BX_SELECTED_CONTROLLER(channel).buffer[i*2] = temp16 & 0x00ff; - BX_SELECTED_CONTROLLER(channel).buffer[i*2+1] = temp16 >> 8; - } -} - - void -bx_hard_drive_c::identify_drive(Bit8u channel) -{ - unsigned i; - Bit32u temp32; - Bit16u temp16; - -#if defined(CONNER_CFA540A) - BX_SELECTED_DRIVE(channel).id_drive[0] = 0x0c5a; - BX_SELECTED_DRIVE(channel).id_drive[1] = 0x0418; - BX_SELECTED_DRIVE(channel).id_drive[2] = 0; - BX_SELECTED_DRIVE(channel).id_drive[3] = BX_SELECTED_DRIVE(channel).hard_drive->heads; - BX_SELECTED_DRIVE(channel).id_drive[4] = 0x9fb7; - BX_SELECTED_DRIVE(channel).id_drive[5] = 0x0289; - BX_SELECTED_DRIVE(channel).id_drive[6] = BX_SELECTED_DRIVE(channel).hard_drive->sectors; - BX_SELECTED_DRIVE(channel).id_drive[7] = 0x0030; - BX_SELECTED_DRIVE(channel).id_drive[8] = 0x000a; - BX_SELECTED_DRIVE(channel).id_drive[9] = 0x0000; - - char* serial_number = " CA00GSQ\0\0\0\0\0\0\0\0\0\0\0\0"; - for (i = 0; i < 10; i++) { - BX_SELECTED_DRIVE(channel).id_drive[10+i] = (serial_number[i*2] << 8) | - serial_number[i*2 + 1]; - } - - BX_SELECTED_DRIVE(channel).id_drive[20] = 3; - BX_SELECTED_DRIVE(channel).id_drive[21] = 512; // 512 Sectors = 256kB cache - BX_SELECTED_DRIVE(channel).id_drive[22] = 4; - - char* firmware = "8FT054 "; - for (i = 0; i < strlen(firmware)/2; i++) { - BX_SELECTED_DRIVE(channel).id_drive[23+i] = (firmware[i*2] << 8) | - firmware[i*2 + 1]; - } - BX_ASSERT((23+i) == 27); - - char* model = "Conner Peripherals 540MB - CFA540A "; - for (i = 0; i < strlen(model)/2; i++) { - BX_SELECTED_DRIVE(channel).id_drive[27+i] = (model[i*2] << 8) | - model[i*2 + 1]; - } - BX_ASSERT((27+i) == 47); - - BX_SELECTED_DRIVE(channel).id_drive[47] = 0x8080; // multiple mode identification - BX_SELECTED_DRIVE(channel).id_drive[48] = 0; - BX_SELECTED_DRIVE(channel).id_drive[49] = 0x0f01; - - BX_SELECTED_DRIVE(channel).id_drive[50] = 0; - - BX_SELECTED_DRIVE(channel).id_drive[51] = 0; - BX_SELECTED_DRIVE(channel).id_drive[52] = 0x0002; - BX_SELECTED_DRIVE(channel).id_drive[53] = 0x0003; - BX_SELECTED_DRIVE(channel).id_drive[54] = 0x0418; - - BX_SELECTED_DRIVE(channel).id_drive[55] = BX_SELECTED_DRIVE(channel).hard_drive->heads; - BX_SELECTED_DRIVE(channel).id_drive[56] = BX_SELECTED_DRIVE(channel).hard_drive->sectors; - - BX_SELECTED_DRIVE(channel).id_drive[57] = 0x1e80; - BX_SELECTED_DRIVE(channel).id_drive[58] = 0x0010; - BX_SELECTED_DRIVE(channel).id_drive[59] = 0x0100 | BX_SELECTED_CONTROLLER(channel).sectors_per_block; - BX_SELECTED_DRIVE(channel).id_drive[60] = 0x20e0; - BX_SELECTED_DRIVE(channel).id_drive[61] = 0x0010; - - BX_SELECTED_DRIVE(channel).id_drive[62] = 0; - - BX_SELECTED_DRIVE(channel).id_drive[63] = 0x0103; // variable (DMA stuff) - BX_SELECTED_DRIVE(channel).id_drive[64] = 0x0001; // PIO - BX_SELECTED_DRIVE(channel).id_drive[65] = 0x00b4; - BX_SELECTED_DRIVE(channel).id_drive[66] = 0x00b4; - BX_SELECTED_DRIVE(channel).id_drive[67] = 0x012c; - BX_SELECTED_DRIVE(channel).id_drive[68] = 0x00b4; - - for (i = 69; i <= 79; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - BX_SELECTED_DRIVE(channel).id_drive[80] = 0; - - BX_SELECTED_DRIVE(channel).id_drive[81] = 0; - - BX_SELECTED_DRIVE(channel).id_drive[82] = 0; - BX_SELECTED_DRIVE(channel).id_drive[83] = 0; - BX_SELECTED_DRIVE(channel).id_drive[84] = 0; - BX_SELECTED_DRIVE(channel).id_drive[85] = 0; - BX_SELECTED_DRIVE(channel).id_drive[86] = 0; - BX_SELECTED_DRIVE(channel).id_drive[87] = 0; - - for (i = 88; i <= 127; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - BX_SELECTED_DRIVE(channel).id_drive[128] = 0x0418; - BX_SELECTED_DRIVE(channel).id_drive[129] = 0x103f; - BX_SELECTED_DRIVE(channel).id_drive[130] = 0x0418; - BX_SELECTED_DRIVE(channel).id_drive[131] = 0x103f; - BX_SELECTED_DRIVE(channel).id_drive[132] = 0x0004; - BX_SELECTED_DRIVE(channel).id_drive[133] = 0xffff; - BX_SELECTED_DRIVE(channel).id_drive[134] = 0; - BX_SELECTED_DRIVE(channel).id_drive[135] = 0x5050; - - for (i = 136; i <= 144; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - BX_SELECTED_DRIVE(channel).id_drive[145] = 0x302e; - BX_SELECTED_DRIVE(channel).id_drive[146] = 0x3245; - BX_SELECTED_DRIVE(channel).id_drive[147] = 0x2020; - BX_SELECTED_DRIVE(channel).id_drive[148] = 0x2020; - - for (i = 149; i <= 255; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - -#else - - // Identify Drive command return values definition - // - // This code is rehashed from some that was donated. - // I'm using ANSI X3.221-1994, AT Attachment Interface for Disk Drives - // and X3T10 2008D Working Draft for ATA-3 - - - // Word 0: general config bit-significant info - // Note: bits 1-5 and 8-14 are now "Vendor specific (obsolete)" - // bit 15: 0=ATA device - // 1=ATAPI device - // bit 14: 1=format speed tolerance gap required - // bit 13: 1=track offset option available - // bit 12: 1=data strobe offset option available - // bit 11: 1=rotational speed tolerance is > 0,5% (typo?) - // bit 10: 1=disk transfer rate > 10Mbs - // bit 9: 1=disk transfer rate > 5Mbs but <= 10Mbs - // bit 8: 1=disk transfer rate <= 5Mbs - // bit 7: 1=removable cartridge drive - // bit 6: 1=fixed drive - // bit 5: 1=spindle motor control option implemented - // bit 4: 1=head switch time > 15 usec - // bit 3: 1=not MFM encoded - // bit 2: 1=soft sectored - // bit 1: 1=hard sectored - // bit 0: 0=reserved - BX_SELECTED_DRIVE(channel).id_drive[0] = 0x0040; - - // Word 1: number of user-addressable cylinders in - // default translation mode. If the value in words 60-61 - // exceed 16,515,072, this word shall contain 16,383. - BX_SELECTED_DRIVE(channel).id_drive[1] = BX_SELECTED_DRIVE(channel).hard_drive->cylinders; - - // Word 2: reserved - BX_SELECTED_DRIVE(channel).id_drive[2] = 0; - - // Word 3: number of user-addressable heads in default - // translation mode - BX_SELECTED_DRIVE(channel).id_drive[3] = BX_SELECTED_DRIVE(channel).hard_drive->heads; - - // Word 4: # unformatted bytes per translated track in default xlate mode - // Word 5: # unformatted bytes per sector in default xlated mode - // Word 6: # user-addressable sectors per track in default xlate mode - // Note: words 4,5 are now "Vendor specific (obsolete)" - BX_SELECTED_DRIVE(channel).id_drive[4] = (512 * BX_SELECTED_DRIVE(channel).hard_drive->sectors); - BX_SELECTED_DRIVE(channel).id_drive[5] = 512; - BX_SELECTED_DRIVE(channel).id_drive[6] = BX_SELECTED_DRIVE(channel).hard_drive->sectors; - - // Word 7-9: Vendor specific - for (i=7; i<=9; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - // Word 10-19: Serial number (20 ASCII characters, 0000h=not specified) - // This field is right justified and padded with spaces (20h). - for (i=10; i<=19; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - // Word 20: buffer type - // 0000h = not specified - // 0001h = single ported single sector buffer which is - // not capable of simulataneous data xfers to/from - // the host and the disk. - // 0002h = dual ported multi-sector buffer capable of - // simulatenous data xfers to/from the host and disk. - // 0003h = dual ported mutli-sector buffer capable of - // simulatenous data xfers with a read caching - // capability. - // 0004h-ffffh = reserved - BX_SELECTED_DRIVE(channel).id_drive[20] = 3; - - // Word 21: buffer size in 512 byte increments, 0000h = not specified - BX_SELECTED_DRIVE(channel).id_drive[21] = 512; // 512 Sectors = 256kB cache - - // Word 22: # of ECC bytes available on read/write long cmds - // 0000h = not specified - BX_SELECTED_DRIVE(channel).id_drive[22] = 4; - - // Word 23..26: Firmware revision (8 ascii chars, 0000h=not specified) - // This field is left justified and padded with spaces (20h) - for (i=23; i<=26; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - // Word 27..46: Model number (40 ascii chars, 0000h=not specified) - // This field is left justified and padded with spaces (20h) -// for (i=27; i<=46; i++) -// BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - for (i=0; i<20; i++) { - BX_SELECTED_DRIVE(channel).id_drive[27+i] = (BX_SELECTED_MODEL(channel)[i*2] << 8) | - BX_SELECTED_MODEL(channel)[i*2 + 1]; - } - - // Word 47: 15-8 Vendor unique - // 7-0 00h= read/write multiple commands not implemented - // xxh= maximum # of sectors that can be transferred - // per interrupt on read and write multiple commands - BX_SELECTED_DRIVE(channel).id_drive[47] = max_multiple_sectors; - - // Word 48: 0000h = cannot perform dword IO - // 0001h = can perform dword IO - BX_SELECTED_DRIVE(channel).id_drive[48] = 1; - - // Word 49: Capabilities - // 15-10: 0 = reserved - // 9: 1 = LBA supported - // 8: 1 = DMA supported - // 7-0: Vendor unique - BX_SELECTED_DRIVE(channel).id_drive[49] = 1<<9; - - // Word 50: Reserved - BX_SELECTED_DRIVE(channel).id_drive[50] = 0; - - // Word 51: 15-8 PIO data transfer cycle timing mode - // 7-0 Vendor unique - BX_SELECTED_DRIVE(channel).id_drive[51] = 0x200; - - // Word 52: 15-8 DMA data transfer cycle timing mode - // 7-0 Vendor unique - BX_SELECTED_DRIVE(channel).id_drive[52] = 0x200; - - // Word 53: 15-1 Reserved - // 0 1=the fields reported in words 54-58 are valid - // 0=the fields reported in words 54-58 may be valid - BX_SELECTED_DRIVE(channel).id_drive[53] = 0; - - // Word 54: # of user-addressable cylinders in curr xlate mode - // Word 55: # of user-addressable heads in curr xlate mode - // Word 56: # of user-addressable sectors/track in curr xlate mode - BX_SELECTED_DRIVE(channel).id_drive[54] = BX_SELECTED_DRIVE(channel).hard_drive->cylinders; - BX_SELECTED_DRIVE(channel).id_drive[55] = BX_SELECTED_DRIVE(channel).hard_drive->heads; - BX_SELECTED_DRIVE(channel).id_drive[56] = BX_SELECTED_DRIVE(channel).hard_drive->sectors; - - // Word 57-58: Current capacity in sectors - // Excludes all sectors used for device specific purposes. - temp32 = - BX_SELECTED_DRIVE(channel).hard_drive->cylinders * - BX_SELECTED_DRIVE(channel).hard_drive->heads * - BX_SELECTED_DRIVE(channel).hard_drive->sectors; - BX_SELECTED_DRIVE(channel).id_drive[57] = (temp32 & 0xffff); // LSW - BX_SELECTED_DRIVE(channel).id_drive[58] = (temp32 >> 16); // MSW - - // Word 59: 15-9 Reserved - // 8 1=multiple sector setting is valid - // 7-0 current setting for number of sectors that can be - // transferred per interrupt on R/W multiple commands - BX_SELECTED_DRIVE(channel).id_drive[59] = 0x0000 | curr_multiple_sectors; - - // Word 60-61: - // If drive supports LBA Mode, these words reflect total # of user - // addressable sectors. This value does not depend on the current - // drive geometry. If the drive does not support LBA mode, these - // words shall be set to 0. - Bit32u num_sects = BX_SELECTED_DRIVE(channel).hard_drive->cylinders * BX_SELECTED_DRIVE(channel).hard_drive->heads * BX_SELECTED_DRIVE(channel).hard_drive->sectors; - BX_SELECTED_DRIVE(channel).id_drive[60] = num_sects & 0xffff; // LSW - BX_SELECTED_DRIVE(channel).id_drive[61] = num_sects >> 16; // MSW - - // Word 62: 15-8 single word DMA transfer mode active - // 7-0 single word DMA transfer modes supported - // The low order byte identifies by bit, all the Modes which are - // supported e.g., if Mode 0 is supported bit 0 is set. - // The high order byte contains a single bit set to indiciate - // which mode is active. - BX_SELECTED_DRIVE(channel).id_drive[62] = 0x0; - - // Word 63: 15-8 multiword DMA transfer mode active - // 7-0 multiword DMA transfer modes supported - // The low order byte identifies by bit, all the Modes which are - // supported e.g., if Mode 0 is supported bit 0 is set. - // The high order byte contains a single bit set to indiciate - // which mode is active. - BX_SELECTED_DRIVE(channel).id_drive[63] = 0x0; - - // Word 64-79 Reserved - for (i=64; i<=79; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - // Word 80: 15-5 reserved - // 4 supports ATA/ATAPI-4 - // 3 supports ATA-3 - // 2 supports ATA-2 - // 1 supports ATA-1 - // 0 reserved - BX_SELECTED_DRIVE(channel).id_drive[80] = (1 << 2) | (1 << 1); - - // Word 81: Minor version number - BX_SELECTED_DRIVE(channel).id_drive[81] = 0; - - // Word 82: 15 obsolete - // 14 NOP command supported - // 13 READ BUFFER command supported - // 12 WRITE BUFFER command supported - // 11 obsolete - // 10 Host protected area feature set supported - // 9 DEVICE RESET command supported - // 8 SERVICE interrupt supported - // 7 release interrupt supported - // 6 look-ahead supported - // 5 write cache supported - // 4 supports PACKET command feature set - // 3 supports power management feature set - // 2 supports removable media feature set - // 1 supports securite mode feature set - // 0 support SMART feature set - BX_SELECTED_DRIVE(channel).id_drive[82] = 1 << 14; - BX_SELECTED_DRIVE(channel).id_drive[83] = 1 << 14; - BX_SELECTED_DRIVE(channel).id_drive[84] = 1 << 14; - BX_SELECTED_DRIVE(channel).id_drive[85] = 1 << 14; - BX_SELECTED_DRIVE(channel).id_drive[86] = 0; - BX_SELECTED_DRIVE(channel).id_drive[87] = 1 << 14; - - for (i=88; i<=127; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - // Word 128-159 Vendor unique - for (i=128; i<=159; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - - // Word 160-255 Reserved - for (i=160; i<=255; i++) - BX_SELECTED_DRIVE(channel).id_drive[i] = 0; - -#endif - - BX_DEBUG(("Drive ID Info. initialized : %04d {%s}", 512, BX_SELECTED_TYPE_STRING(channel))); - - // now convert the id_drive array (native 256 word format) to - // the controller buffer (512 bytes) - for (i=0; i<=255; i++) { - temp16 = BX_SELECTED_DRIVE(channel).id_drive[i]; - BX_SELECTED_CONTROLLER(channel).buffer[i*2] = temp16 & 0x00ff; - BX_SELECTED_CONTROLLER(channel).buffer[i*2+1] = temp16 >> 8; - } -} - - void BX_CPP_AttrRegparmN(3) -bx_hard_drive_c::init_send_atapi_command(Bit8u channel, Bit8u command, int req_length, int alloc_length, bool lazy) -{ - // BX_SELECTED_CONTROLLER(channel).byte_count is a union of BX_SELECTED_CONTROLLER(channel).cylinder_no; - // lazy is used to force a data read in the buffer at the next read. - - if (BX_SELECTED_CONTROLLER(channel).byte_count == 0xffff) - BX_SELECTED_CONTROLLER(channel).byte_count = 0xfffe; - - if ((BX_SELECTED_CONTROLLER(channel).byte_count & 1) - && !(alloc_length <= BX_SELECTED_CONTROLLER(channel).byte_count)) { - BX_INFO(("Odd byte count (0x%04x) to ATAPI command 0x%02x, using 0x%04x", - BX_SELECTED_CONTROLLER(channel).byte_count, command, BX_SELECTED_CONTROLLER(channel).byte_count - 1)); - BX_SELECTED_CONTROLLER(channel).byte_count -= 1; - } - - if (BX_SELECTED_CONTROLLER(channel).byte_count == 0) - BX_PANIC(("ATAPI command with zero byte count")); - - if (alloc_length < 0) - BX_PANIC(("Allocation length < 0")); - if (alloc_length == 0) - alloc_length = BX_SELECTED_CONTROLLER(channel).byte_count; - - BX_SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1; - BX_SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 0; - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drq = 1; - BX_SELECTED_CONTROLLER(channel).status.err = 0; - - // no bytes transfered yet - if (lazy) - BX_SELECTED_CONTROLLER(channel).buffer_index = 2048; - else - BX_SELECTED_CONTROLLER(channel).buffer_index = 0; - BX_SELECTED_CONTROLLER(channel).drq_index = 0; - - if (BX_SELECTED_CONTROLLER(channel).byte_count > req_length) - BX_SELECTED_CONTROLLER(channel).byte_count = req_length; - - if (BX_SELECTED_CONTROLLER(channel).byte_count > alloc_length) - BX_SELECTED_CONTROLLER(channel).byte_count = alloc_length; - - BX_SELECTED_DRIVE(channel).atapi.command = command; - BX_SELECTED_DRIVE(channel).atapi.drq_bytes = BX_SELECTED_CONTROLLER(channel).byte_count; - BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining = (req_length < alloc_length) ? req_length : alloc_length; - - // if (lazy) { - // // bias drq_bytes and total_bytes_remaining - // BX_SELECTED_DRIVE(channel).atapi.drq_bytes += 2048; - // BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining += 2048; - // } -} - -void -bx_hard_drive_c::atapi_cmd_error(Bit8u channel, sense_t sense_key, asc_t asc) -{ - BX_ERROR(("atapi_cmd_error channel=%02x key=%02x asc=%02x", channel, sense_key, asc)); - - BX_SELECTED_CONTROLLER(channel).error_register = sense_key << 4; - BX_SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1; - BX_SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 1; - BX_SELECTED_CONTROLLER(channel).interrupt_reason.rel = 0; - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.write_fault = 0; - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 1; - - BX_SELECTED_DRIVE(channel).sense.sense_key = sense_key; - BX_SELECTED_DRIVE(channel).sense.asc = asc; - BX_SELECTED_DRIVE(channel).sense.ascq = 0; -} - -void BX_CPP_AttrRegparmN(1) -bx_hard_drive_c::atapi_cmd_nop(Bit8u channel) -{ - BX_SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1; - BX_SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 1; - BX_SELECTED_CONTROLLER(channel).interrupt_reason.rel = 0; - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).status.err = 0; -} - -void -bx_hard_drive_c::init_mode_sense_single(Bit8u channel, const void* src, int size) -{ - // Header - BX_SELECTED_CONTROLLER(channel).buffer[0] = (size+6) >> 8; - BX_SELECTED_CONTROLLER(channel).buffer[1] = (size+6) & 0xff; - BX_SELECTED_CONTROLLER(channel).buffer[2] = 0x70; // no media present - BX_SELECTED_CONTROLLER(channel).buffer[3] = 0; // reserved - BX_SELECTED_CONTROLLER(channel).buffer[4] = 0; // reserved - BX_SELECTED_CONTROLLER(channel).buffer[5] = 0; // reserved - BX_SELECTED_CONTROLLER(channel).buffer[6] = 0; // reserved - BX_SELECTED_CONTROLLER(channel).buffer[7] = 0; // reserved - - // Data - memcpy(BX_SELECTED_CONTROLLER(channel).buffer + 8, src, size); -} - - void BX_CPP_AttrRegparmN(1) -bx_hard_drive_c::ready_to_send_atapi(Bit8u channel) -{ - raise_interrupt(channel); -} - -void BX_CPP_AttrRegparmN(1) -bx_hard_drive_c::raise_interrupt(Bit8u channel) -{ - BX_DEBUG(("raise_interrupt called, disable_irq = %02x", BX_SELECTED_CONTROLLER(channel).control.disable_irq)); - if (!BX_SELECTED_CONTROLLER(channel).control.disable_irq) { BX_DEBUG(("raising interrupt")); } else { BX_DEBUG(("Not raising interrupt")); } - if (!BX_SELECTED_CONTROLLER(channel).control.disable_irq) { - Bit32u irq = BX_HD_THIS channels[channel].irq; - BX_DEBUG(("Raising interrupt %d {%s}", irq, BX_SELECTED_TYPE_STRING(channel))); - DEV_pic_raise_irq(irq); - } else { - if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) - BX_INFO(("Interrupt masked {%s}", BX_SELECTED_TYPE_STRING(channel))); - } -} - - void -bx_hard_drive_c::command_aborted(Bit8u channel, unsigned value) -{ - BX_DEBUG(("aborting on command 0x%02x {%s}", value, BX_SELECTED_TYPE_STRING(channel))); - BX_SELECTED_CONTROLLER(channel).current_command = 0; - BX_SELECTED_CONTROLLER(channel).status.busy = 0; - BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1; - BX_SELECTED_CONTROLLER(channel).status.err = 1; - BX_SELECTED_CONTROLLER(channel).error_register = 0x04; // command ABORTED - BX_SELECTED_CONTROLLER(channel).status.drq = 0; - BX_SELECTED_CONTROLLER(channel).status.seek_complete = 0; - BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0; - BX_SELECTED_CONTROLLER(channel).buffer_index = 0; - raise_interrupt(channel); -} - - Bit32u -bx_hard_drive_c::get_device_handle(Bit8u channel, Bit8u device) -{ - BX_DEBUG(("get_device_handle %d %d",channel, device)); - if ((channel < BX_MAX_ATA_CHANNEL) && (device < 2)) { - return ((channel*2) + device); - } - - return BX_MAX_ATA_CHANNEL*2; -} - - Bit32u -bx_hard_drive_c::get_first_cd_handle(void) -{ - for (Bit8u channel=0; channel= BX_MAX_ATA_CHANNEL*2 ) return 0; - - Bit8u channel = handle / 2; - Bit8u device = handle % 2; - return( BX_HD_THIS channels[channel].drives[device].cdrom.ready ); -} - - unsigned -bx_hard_drive_c::set_cd_media_status(Bit32u handle, unsigned status) -{ - BX_DEBUG (("set_cd_media_status handle=%d status=%d", handle, status)); - if ( handle >= BX_MAX_ATA_CHANNEL*2 ) return 0; - - Bit8u channel = handle / 2; - Bit8u device = handle % 2; - - // if setting to the current value, nothing to do - if (status == BX_HD_THIS channels[channel].drives[device].cdrom.ready) - return(status); - // return 0 if no cdromd is present - if (!BX_DRIVE_IS_CD(channel,device)) - return(0); - - if (status == 0) { - // eject cdrom if not locked by guest OS - if (BX_HD_THIS channels[channel].drives[device].cdrom.locked) return(1); - else { -#ifdef LOWLEVEL_CDROM - BX_HD_THIS channels[channel].drives[device].cdrom.cd->eject_cdrom(); -#endif - BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0; - bx_options.atadevice[channel][device].Ostatus->set(BX_EJECTED); - } - } - else { - // insert cdrom -#ifdef LOWLEVEL_CDROM - if (BX_HD_THIS channels[channel].drives[device].cdrom.cd->insert_cdrom(bx_options.atadevice[channel][device].Opath->getptr())) { - BX_INFO(( "Media present in CD-ROM drive")); - BX_HD_THIS channels[channel].drives[device].cdrom.ready = 1; - BX_HD_THIS channels[channel].drives[device].cdrom.capacity = BX_HD_THIS channels[channel].drives[device].cdrom.cd->capacity(); - bx_options.atadevice[channel][device].Ostatus->set(BX_INSERTED); - BX_SELECTED_DRIVE(channel).sense.sense_key = SENSE_UNIT_ATTENTION; - BX_SELECTED_DRIVE(channel).sense.asc = 0; - BX_SELECTED_DRIVE(channel).sense.ascq = 0; - raise_interrupt(channel); - } - else { -#endif - BX_INFO(( "Could not locate CD-ROM, continuing with media not present")); - BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0; - bx_options.atadevice[channel][device].Ostatus->set(BX_EJECTED); -#ifdef LOWLEVEL_CDROM - } -#endif - } - return( BX_HD_THIS channels[channel].drives[device].cdrom.ready ); -} - - -/*** default_image_t function definitions ***/ - -int default_image_t::open (const char* pathname) -{ - return open(pathname, O_RDWR); -} - -int default_image_t::open (const char* pathname, int flags) -{ - fd = ::open(pathname, flags -#ifdef O_BINARY - | O_BINARY -#endif - ); - - if (fd < 0) { - return fd; - } - - /* look at size of image file to calculate disk geometry */ - struct stat stat_buf; - int ret = fstat(fd, &stat_buf); - if (ret) { - BX_PANIC(("fstat() returns error!")); - } - - return fd; -} - -void default_image_t::close () -{ - if (fd > -1) { - ::close(fd); - } -} - -off_t default_image_t::lseek (off_t offset, int whence) -{ - return ::lseek(fd, offset, whence); -} - -ssize_t default_image_t::read (void* buf, size_t count) -{ - return ::read(fd, (char*) buf, count); -} - -ssize_t default_image_t::write (const void* buf, size_t count) -{ - return ::write(fd, (char*) buf, count); -} - -char increment_string (char *str, int diff) -{ - // find the last character of the string, and increment it. - char *p = str; - while (*p != 0) p++; - BX_ASSERT (p>str); // choke on zero length strings - p--; // point to last character of the string - (*p) += diff; // increment to next/previous ascii code. - BX_DEBUG(("increment string returning '%s'", str)); - return (*p); -} - -/*** concat_image_t function definitions ***/ - -concat_image_t::concat_image_t () -{ - fd = -1; -} - -void concat_image_t::increment_string (char *str) -{ - ::increment_string(str, +1); -} - -int concat_image_t::open (const char* pathname0) -{ - char *pathname = strdup (pathname0); - BX_DEBUG(("concat_image_t.open")); - off_t start_offset = 0; - for (int i=0; i -1) { - ::close(fd); - } -} - -off_t concat_image_t::lseek (off_t offset, int whence) -{ - if ((offset % 512) != 0) - BX_PANIC( ("lseek HD with offset not multiple of 512")); - BX_DEBUG(("concat_image_t.lseek(%d)", whence)); - // is this offset in this disk image? - if (offset < thismin) { - // no, look at previous images - for (int i=index-1; i>=0; i--) { - if (offset >= start_offset_table[i]) { - index = i; - fd = fd_table[i]; - thismin = start_offset_table[i]; - thismax = thismin + length_table[i] - 1; - BX_DEBUG(("concat_image_t.lseek to earlier image, index=%d", index)); - break; - } - } - } else if (offset > thismax) { - // no, look at later images - for (int i=index+1; i= length_table[index]) { - BX_PANIC(("concat_image_t.lseek to byte %ld failed", (long)offset)); - return -1; - } - - seek_was_last_op = 1; - return ::lseek(fd, offset, whence); -} - -ssize_t concat_image_t::read (void* buf, size_t count) -{ - if (bx_dbg.disk) - BX_DEBUG(("concat_image_t.read %ld bytes", (long)count)); - // notice if anyone does sequential read or write without seek in between. - // This can be supported pretty easily, but needs additional checks for - // end of a partial image. - if (!seek_was_last_op) - BX_PANIC( ("no seek before read")); - return ::read(fd, (char*) buf, count); -} - -ssize_t concat_image_t::write (const void* buf, size_t count) -{ - BX_DEBUG(("concat_image_t.write %ld bytes", (long)count)); - // notice if anyone does sequential read or write without seek in between. - // This can be supported pretty easily, but needs additional checks for - // end of a partial image. - if (!seek_was_last_op) - BX_PANIC( ("no seek before write")); - return ::write(fd, (char*) buf, count); -} - -/*** sparse_image_t function definitions ***/ -sparse_image_t::sparse_image_t () -{ - fd = -1; - pathname = NULL; -#ifdef _POSIX_MAPPED_FILES - mmap_header = NULL; -#endif - pagetable = NULL; -} - - -/* -void showpagetable(uint32 * pagetable, size_t numpages) -{ - printf("Non null pages: "); - for (int i = 0; i < numpages; i++) - { - if (pagetable[i] != 0xffffffff) - { - printf("%d ", i); - } - } - printf("\n"); -} -*/ - - -void sparse_image_t::read_header() -{ - BX_ASSERT(sizeof(header) == SPARSE_HEADER_SIZE); - - int ret = ::read(fd, &header, sizeof(header)); - - if (-1 == ret) - { - panic(strerror(errno)); - } - - if (sizeof(header) != ret) - { - panic("could not read entire header"); - } - - if (dtoh32(header.magic) != SPARSE_HEADER_MAGIC) - { - panic("failed header magic check"); - } - - if (dtoh32(header.version) != 1) - { - panic("unknown version in header"); - } - - pagesize = dtoh32(header.pagesize); - uint32 numpages = dtoh32(header.numpages); - - total_size = pagesize; - total_size *= numpages; - - pagesize_shift = 0; - while ((pagesize >> pagesize_shift) > 1) pagesize_shift++; - - if ((uint32)(1 << pagesize_shift) != pagesize) - { - panic("failed block size header check"); - } - - pagesize_mask = pagesize - 1; - - size_t preamble_size = (sizeof(uint32) * numpages) + sizeof(header); - data_start = 0; - while (data_start < preamble_size) data_start += pagesize; - - bool did_mmap = false; - -#ifdef _POSIX_MAPPED_FILES -// Try to memory map from the beginning of the file (0 is trivially a page multiple) - void * mmap_header = mmap(NULL, preamble_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (mmap_header == MAP_FAILED) - { - BX_INFO(("failed to mmap sparse disk file - using conventional file access")); - mmap_header = NULL; - } - else - { - mmap_length = preamble_size; - did_mmap = true; - pagetable = ((uint32 *) (((uint8 *) mmap_header) + sizeof(header))); - -// system_pagesize = getpagesize(); - system_pagesize_mask = getpagesize() - 1; - } -#endif - - if (!did_mmap) - { - pagetable = new uint32[numpages]; - - if (pagetable == NULL) - { - panic("could not allocate memory for sparse disk block table"); - } - - ret = ::read(fd, pagetable, sizeof(uint32) * numpages); - - if (-1 == ret) - { - panic(strerror(errno)); - } - - if ((int)(sizeof(uint32) * numpages) != ret) - { - panic("could not read entire block table"); - } - } -} - -int sparse_image_t::open (const char* pathname0) -{ - pathname = strdup(pathname0); - BX_DEBUG(("sparse_image_t.open")); - - fd = ::open(pathname, O_RDWR -#ifdef O_BINARY - | O_BINARY -#endif - ); - - if (fd < 0) - { - // open failed. - return -1; - } - BX_DEBUG(("sparse_image: open image %s", pathname)); - - read_header(); - - struct stat stat_buf; - if (0 != fstat(fd, &stat_buf)) panic(("fstat() returns error!")); - - underlying_filesize = stat_buf.st_size; - - if ((underlying_filesize % pagesize) != 0) - panic("size of sparse disk image is not multiple of page size"); - - underlying_current_filepos = 0; - if (-1 == ::lseek(fd, 0, SEEK_SET)) - panic("error while seeking to start of file"); - - lseek(0, SEEK_SET); - - //showpagetable(pagetable, header.numpages); - - char * parentpathname = strdup(pathname); - char lastchar = ::increment_string(parentpathname, -1); - - if ((lastchar >= '0') && (lastchar <= '9')) - { - struct stat stat_buf; - if (0 == stat(parentpathname, &stat_buf)) - { - parent_image = new sparse_image_t(); - int ret = parent_image->open(parentpathname); - if (ret != 0) return ret; - if ( (parent_image->pagesize != pagesize) - || (parent_image->total_size != total_size)) - { - panic("child drive image does not have same page count/page size configuration"); - } - } - } - - if (parentpathname != NULL) free(parentpathname); - - return 0; // success. -} - -void sparse_image_t::close () -{ - BX_DEBUG(("concat_image_t.close")); - if (pathname != NULL) - { - free(pathname); - } -#ifdef _POSIX_MAPPED_FILES - if (mmap_header != NULL) - { - int ret = munmap(mmap_header, mmap_length); - if (ret != 0) - BX_INFO(("failed to un-memory map sparse disk file")); - } - pagetable = NULL; // We didn't malloc it -#endif - if (fd > -1) { - ::close(fd); - } - if (pagetable != NULL) - { - delete [] pagetable; - } - if (parent_image != NULL) - { - delete parent_image; - } -} - -off_t sparse_image_t::lseek (off_t offset, int whence) -{ - //showpagetable(pagetable, header.numpages); - - if ((offset % 512) != 0) - BX_PANIC( ("lseek HD with offset not multiple of 512")); - if (whence != SEEK_SET) - BX_PANIC( ("lseek HD with whence not SEEK_SET")); - - BX_DEBUG(("sparse_image_t.lseek(%d)", whence)); - - if (offset > total_size) - { - BX_PANIC(("sparse_image_t.lseek to byte %ld failed", (long)offset)); - return -1; - } - - //printf("Seeking to position %ld\n", (long) offset); - - set_virtual_page(offset >> pagesize_shift); - position_page_offset = offset & pagesize_mask; - - return 0; -} - -inline off_t sparse_image_t::get_physical_offset() -{ - off_t physical_offset = data_start; - physical_offset += (position_physical_page << pagesize_shift); - physical_offset += position_page_offset; - - return physical_offset; -} - -inline void sparse_image_t::set_virtual_page(uint32 new_virtual_page) -{ - position_virtual_page = new_virtual_page; - - position_physical_page = dtoh32(pagetable[position_virtual_page]); -} - -ssize_t sparse_image_t::read_page_fragment(uint32 read_virtual_page, uint32 read_page_offset, size_t read_size, void * buf) -{ - if (read_virtual_page != position_virtual_page) - { - set_virtual_page(read_virtual_page); - } - - position_page_offset = read_page_offset; - - if (position_physical_page == SPARSE_PAGE_NOT_ALLOCATED) - { - if (parent_image != NULL) - { - return parent_image->read_page_fragment(read_virtual_page, read_page_offset, read_size, buf); - } - else - { - memset(buf, 0, read_size); - } - } - else - { - off_t physical_offset = get_physical_offset(); - - if (physical_offset != underlying_current_filepos) - { - int ret = ::lseek(fd, physical_offset, SEEK_SET); - // underlying_current_filepos update deferred - if (ret == -1) - panic(strerror(errno)); - } - - //printf("Reading %s at position %ld size %d\n", pathname, (long) physical_offset, (long) read_size); - ssize_t readret = ::read(fd, buf, read_size); - - if (readret == -1) - { - panic(strerror(errno)); - } - - if ((size_t)readret != read_size) - { - panic("could not read block contents from file"); - } - - underlying_current_filepos = physical_offset + read_size; - } - - return read_size; -} - -ssize_t sparse_image_t::read(void* buf, size_t count) -{ - //showpagetable(pagetable, header.numpages); - ssize_t total_read = 0; - - if (bx_dbg.disk) - BX_DEBUG(("sparse_image_t.read %ld bytes", (long)count)); - - while (count != 0) - { - size_t can_read = pagesize - position_page_offset; - if (count < can_read) can_read = count; - - BX_ASSERT (can_read != 0); - - size_t was_read = read_page_fragment(position_virtual_page, position_page_offset, can_read, buf); - - BX_ASSERT(was_read == can_read); - - total_read += can_read; - - position_page_offset += can_read; - if (position_page_offset == pagesize) - { - position_page_offset = 0; - set_virtual_page(position_virtual_page + 1); - } - - BX_ASSERT(position_page_offset < pagesize); - - buf = (((uint8 *) buf) + can_read); - count -= can_read; - } - - return total_read; -} - -void sparse_image_t::panic(const char * message) -{ - char buffer[1024]; - if (message == NULL) - { - snprintf(buffer, sizeof(buffer), "error with sparse disk image %s", pathname); - } - else - { - snprintf(buffer, sizeof(buffer), "error with sparse disk image %s - %s", pathname, message); - } - BX_PANIC((buffer)); -} - -ssize_t sparse_image_t::write (const void* buf, size_t count) -{ - //showpagetable(pagetable, header.numpages); - - ssize_t total_written = 0; - - uint32 update_pagetable_start = position_virtual_page; - uint32 update_pagetable_count = 0; - - if (bx_dbg.disk) - BX_DEBUG(("sparse_image_t.write %ld bytes", (long)count)); - - while (count != 0) - { - size_t can_write = pagesize - position_page_offset; - if (count < can_write) can_write = count; - - BX_ASSERT (can_write != 0); - - if (position_physical_page == SPARSE_PAGE_NOT_ALLOCATED) - { - // We just add on another page at the end of the file - // Reclamation, compaction etc should currently be done off-line - - size_t data_size = underlying_filesize - data_start; - BX_ASSERT((data_size % pagesize) == 0); - - - uint32 data_size_pages = data_size / pagesize; - uint32 next_data_page = data_size_pages; - - pagetable[position_virtual_page] = htod32(next_data_page); - position_physical_page = next_data_page; - - off_t page_file_start = data_start + (position_physical_page << pagesize_shift); - - if (parent_image != NULL) - { - // If we have a parent, we must merge our portion with the parent - void * writebuffer = NULL; - - if (can_write == pagesize) - { - writebuffer = (void *) buf; - } - else - { - writebuffer = malloc(pagesize); - if (writebuffer == NULL) - panic("Cannot allocate sufficient memory for page-merge in write"); - - // Read entire page - could optimize, but simple for now - parent_image->read_page_fragment(position_virtual_page, 0, pagesize, writebuffer); - - void * dest_start = ((uint8 *) writebuffer) + position_page_offset; - memcpy(dest_start, buf, can_write); - } - - int ret; - ret = ::lseek(fd, page_file_start, SEEK_SET); - // underlying_current_filepos update deferred - if (-1 == ret) panic(strerror(errno)); - - ret = ::write(fd, writebuffer, pagesize); - - if (-1 == ret) panic(strerror(errno)); - - if (pagesize != (uint32)ret) panic("failed to write entire merged page to disk"); - - if (can_write != pagesize) - { - free(writebuffer); - } - } - else - { - // We need to write a zero page because read has been returning zeroes - // We seek as close to the page end as possible, and then write a little - // This produces a sparse file which has blanks - // Also very quick, even when pagesize is massive - int ret; - ret = ::lseek(fd, page_file_start + pagesize - 4, SEEK_SET); - // underlying_current_filepos update deferred - if (-1 == ret) panic(strerror(errno)); - - uint32 zero = 0; - ret = ::write(fd, &zero, 4); - - if (-1 == ret) panic(strerror(errno)); - - if (4 != ret) panic("failed to write entire blank page to disk"); - } - - update_pagetable_count = (position_virtual_page - update_pagetable_start) + 1; - underlying_filesize = underlying_current_filepos = page_file_start + pagesize; - } - - BX_ASSERT(position_physical_page != SPARSE_PAGE_NOT_ALLOCATED); - - off_t physical_offset = get_physical_offset(); - - if (physical_offset != underlying_current_filepos) - { - int ret = ::lseek(fd, physical_offset, SEEK_SET); - // underlying_current_filepos update deferred - if (ret == -1) - panic(strerror(errno)); - } - - //printf("Writing at position %ld size %d\n", (long) physical_offset, can_write); - ssize_t writeret = ::write(fd, buf, can_write); - - if (writeret == -1) - { - panic(strerror(errno)); - } - - if ((size_t)writeret != can_write) - { - panic("could not write block contents to file"); - } - - underlying_current_filepos = physical_offset + can_write; - - total_written += can_write; - - position_page_offset += can_write; - if (position_page_offset == pagesize) - { - position_page_offset = 0; - set_virtual_page(position_virtual_page + 1); - } - - BX_ASSERT(position_page_offset < pagesize); - - buf = (((uint8 *) buf) + can_write); - count -= can_write; - } - - if (update_pagetable_count != 0) - { - bool done = false; - off_t pagetable_write_from = sizeof(header) + (sizeof(uint32) * update_pagetable_start); - size_t write_bytecount = update_pagetable_count * sizeof(uint32); - -#ifdef _POSIX_MAPPED_FILES - if (mmap_header != NULL) - { - // Sync from the beginning of the page - size_t system_page_offset = pagetable_write_from & system_pagesize_mask; - void * start = ((uint8 *) mmap_header + pagetable_write_from - system_page_offset); - - int ret = msync(start, system_page_offset + write_bytecount, MS_ASYNC); - - if (ret != 0) - panic(strerror(errno)); - - done = true; - } -#endif - - if (!done) - { - int ret = ::lseek(fd, pagetable_write_from, SEEK_SET); - // underlying_current_filepos update deferred - if (ret == -1) panic(strerror(errno)); - - //printf("Writing header at position %ld size %ld\n", (long) pagetable_write_from, (long) write_bytecount); - ret = ::write(fd, &pagetable[update_pagetable_start], write_bytecount); - if (ret == -1) panic(strerror(errno)); - if ((size_t)ret != write_bytecount) panic("could not write entire updated block header"); - - underlying_current_filepos = pagetable_write_from + write_bytecount; - } - } - - return total_written; -} - -#if DLL_HD_SUPPORT -/*** dll_image_t function definitions ***/ - -/* -function vdisk_open(path:PChar;numclusters,clustersize:integer):integer; -procedure vdisk_read(vunit:integer;blk:integer;var buf:TBlock); -procedure vdisk_write(vunit:integer;blk:integer;var buf:TBlock); -procedure vdisk_close(vunit:integer); -*/ - -HINSTANCE hlib_vdisk = 0; - -int (*vdisk_open) (const char *path,int numclusters,int clustersize); -void (*vdisk_read) (int vunit,int blk,void *buf); -void (*vdisk_write) (int vunit,int blk,const void *buf); -void (*vdisk_close) (int vunit); - -int dll_image_t::open (const char* pathname) -{ - if (hlib_vdisk == 0) { - hlib_vdisk = LoadLibrary("vdisk.dll"); - if (hlib_vdisk != 0) { - vdisk_read = (void (*)(int,int,void*)) GetProcAddress(hlib_vdisk,"vdisk_read"); - vdisk_write = (void (*)(int,int,const void*)) GetProcAddress(hlib_vdisk,"vdisk_write"); - vdisk_open = (int (*)(const char *,int,int)) GetProcAddress(hlib_vdisk,"vdisk_open"); - vdisk_close = (void (*)(int)) GetProcAddress(hlib_vdisk,"vdisk_close"); - } - } - if (hlib_vdisk != 0) { - vunit = vdisk_open(pathname,0x10000,64); - vblk = 0; - } else { - vunit = -2; - } - return vunit; -} - -void dll_image_t::close () -{ - if (vunit >= 0 && hlib_vdisk != 0) { - vdisk_close(vunit); - } -} - -off_t dll_image_t::lseek (off_t offset, int whence) -{ - vblk = offset >> 9; - return 0; -} - -ssize_t dll_image_t::read (void* buf, size_t count) -{ - if (vunit >= 0 && hlib_vdisk != 0) { - vdisk_read(vunit,vblk,buf); - return count; - } else { - return -1; - } -} - -ssize_t dll_image_t::write (const void* buf, size_t count) -{ - if (vunit >= 0 && hlib_vdisk != 0) { - vdisk_write(vunit,vblk,buf); - return count; - } else { - return -1; - } -} -#endif // DLL_HD_SUPPORT - -error_recovery_t::error_recovery_t () -{ - if (sizeof(error_recovery_t) != 8) { - BX_PANIC(("error_recovery_t has size != 8")); - } - - data[0] = 0x01; - data[1] = 0x06; - data[2] = 0x00; - data[3] = 0x05; // Try to recover 5 times - data[4] = 0x00; - data[5] = 0x00; - data[6] = 0x00; - data[7] = 0x00; -} - -uint16 BX_CPP_AttrRegparmN(1) -read_16bit(const uint8* buf) -{ - return (buf[0] << 8) | buf[1]; -} - -uint32 BX_CPP_AttrRegparmN(1) -read_32bit(const uint8* buf) -{ - return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; -} - -// redolog implementation -redolog_t::redolog_t () -{ - fd = -1; - catalog = NULL; - bitmap = NULL; - extent_index = (Bit32u)0; - extent_offset = (Bit32u)0; - extent_next = (Bit32u)0; -} - -void -redolog_t::print_header() -{ - BX_INFO(("redolog : Standard Header : magic='%s', type='%s', subtype='%s', version = %d.%d", - header.standard.magic, header.standard.type, header.standard.subtype, - dtoh32(header.standard.version)/0x10000, - dtoh32(header.standard.version)%0x10000)); - BX_INFO(("redolog : Specific Header : #entries=%d, bitmap size=%d, exent size = %d disk size = %lld", - dtoh32(header.specific.catalog), - dtoh32(header.specific.bitmap), - dtoh32(header.specific.extent), - dtoh64(header.specific.disk))); -} - -int -redolog_t::make_header (const char* type, Bit64u size) -{ - Bit32u entries, extent_size, bitmap_size; - Bit64u maxsize; - Bit32u flip=0; - - // Set standard header values - strcpy((char*)header.standard.magic, STANDARD_HEADER_MAGIC); - strcpy((char*)header.standard.type, REDOLOG_TYPE); - strcpy((char*)header.standard.subtype, type); - header.standard.version = htod32(STANDARD_HEADER_VERSION); - header.standard.header = htod32(STANDARD_HEADER_SIZE); - - entries = 512; - bitmap_size = 1; - - // Compute #entries and extent size values - do { - extent_size = 8 * bitmap_size * 512; - - header.specific.catalog = htod32(entries); - header.specific.bitmap = htod32(bitmap_size); - header.specific.extent = htod32(extent_size); - - maxsize = (Bit64u)entries * (Bit64u)extent_size; - - flip++; - - if(flip&0x01) bitmap_size *= 2; - else entries *= 2; - } while (maxsize < size); - - header.specific.disk = htod64(size); - - print_header(); - - catalog = (Bit32u*)malloc(dtoh32(header.specific.catalog) * sizeof(Bit32u)); - bitmap = (Bit8u*)malloc(dtoh32(header.specific.bitmap)); - - if ((catalog == NULL) || (bitmap==NULL)) - BX_PANIC(("redolog : could not malloc catalog or bitmap")); - - for (Bit32u i=0; i= extent_next) - extent_next = dtoh32(catalog[i]) + 1; - } - } - BX_INFO(("redolog : next extent will be at index %d",extent_next)); - - // memory used for storing bitmaps - bitmap = (Bit8u *)malloc(dtoh32(header.specific.bitmap)); - - bitmap_blocs = 1 + (dtoh32(header.specific.bitmap) - 1) / 512; - extent_blocs = 1 + (dtoh32(header.specific.extent) - 1) / 512; - - BX_DEBUG(("redolog : each bitmap is %d blocs", bitmap_blocs)); - BX_DEBUG(("redolog : each extent is %d blocs", extent_blocs)); - - return 0; -} - -void -redolog_t::close () -{ - if (fd >= 0) - ::close(fd); - - if (catalog != NULL) - free(catalog); - - if (bitmap != NULL) - free(bitmap); -} - -off_t -redolog_t::lseek (off_t offset, int whence) -{ - if ((offset % 512) != 0) { - BX_PANIC( ("redolog : lseek HD with offset not multiple of 512")); - return -1; - } - if (whence != SEEK_SET) { - BX_PANIC( ("redolog : lseek HD with whence not SEEK_SET")); - return -1; - } - if (offset > (off_t)dtoh64(header.specific.disk)) - { - BX_PANIC(("redolog : lseek to byte %ld failed", (long)offset)); - return -1; - } - - extent_index = offset / dtoh32(header.specific.extent); - extent_offset = (offset % dtoh32(header.specific.extent)) / 512; - - BX_DEBUG(("redolog : lseeking extent index %d, offset %d",extent_index, extent_offset)); - - return offset; -} - -ssize_t -redolog_t::read (void* buf, size_t count) -{ - off_t bloc_offset, bitmap_offset; - - if (count != 512) - BX_PANIC( ("redolog : read HD with count not 512")); - - BX_DEBUG(("redolog : reading index %d, mapping to %d", extent_index, dtoh32(catalog[extent_index]))); - - if (dtoh32(catalog[extent_index]) == REDOLOG_PAGE_NOT_ALLOCATED) - { - // page not allocated - return 0; - } - - bitmap_offset = (off_t)STANDARD_HEADER_SIZE + (dtoh32(header.specific.catalog) * sizeof(Bit32u)); - bitmap_offset += (off_t)512 * dtoh32(catalog[extent_index]) * (extent_blocs + bitmap_blocs); - bloc_offset = bitmap_offset + ((off_t)512 * (bitmap_blocs + extent_offset)); - - BX_DEBUG(("redolog : bitmap offset is %x", (Bit32u)bitmap_offset)); - BX_DEBUG(("redolog : bloc offset is %x", (Bit32u)bloc_offset)); - - - // FIXME if same extent_index as before we can skip bitmap read - - ::lseek(fd, bitmap_offset, SEEK_SET); - - if (::read(fd, bitmap, dtoh32(header.specific.bitmap)) != (ssize_t)dtoh32(header.specific.bitmap)) - { - BX_PANIC(("redolog : failed to read bitmap for extent %d", extent_index)); - return 0; - } - - if ( ((bitmap[extent_offset/8] >> (extent_offset%8)) & 0x01) == 0x00 ) - { - BX_DEBUG(("read not in redolog")); - - // bitmap says bloc not in reloglog - return 0; - } - - ::lseek(fd, bloc_offset, SEEK_SET); - - return (::read(fd, buf, count)); -} - -ssize_t -redolog_t::write (const void* buf, size_t count) -{ - Bit32u i; - off_t bloc_offset, bitmap_offset, catalog_offset; - ssize_t written; - bx_bool update_catalog = 0; - - if (count != 512) - BX_PANIC( ("redolog : write HD with count not 512")); - - BX_DEBUG(("redolog : writing index %d, mapping to %d", extent_index, dtoh32(catalog[extent_index]))); - if (dtoh32(catalog[extent_index]) == REDOLOG_PAGE_NOT_ALLOCATED) - { - if(extent_next >= dtoh32(header.specific.catalog)) - { - BX_PANIC(("redolog : can't allocate new extent... catalog is full")); - return 0; - } - - BX_DEBUG(("redolog : allocating new extent at %d", extent_next)); - - // Extent not allocated, allocate new - catalog[extent_index] = htod32(extent_next); - - extent_next += 1; - - char *zerobuffer = (char*)malloc(512); - memset(zerobuffer, 0, 512); - - // Write bitmap - bitmap_offset = (off_t)STANDARD_HEADER_SIZE + (dtoh32(header.specific.catalog) * sizeof(Bit32u)); - bitmap_offset += (off_t)512 * dtoh32(catalog[extent_index]) * (extent_blocs + bitmap_blocs); - ::lseek(fd, bitmap_offset, SEEK_SET); - for(i=0; i> (extent_offset%8)) & 0x01) == 0x00 ) - { - bitmap[extent_offset/8] |= 1 << (extent_offset%8); - ::lseek(fd, bitmap_offset, SEEK_SET); - ::write(fd, bitmap, dtoh32(header.specific.bitmap)); - } - - // Write catalog - if (update_catalog) - { - // FIXME if mmap - catalog_offset = (off_t)STANDARD_HEADER_SIZE + (extent_index * sizeof(Bit32u)); - - BX_DEBUG(("redolog : writing catalog at offset %x", (Bit32u)catalog_offset)); - - ::lseek(fd, catalog_offset, SEEK_SET); - ::write(fd, &catalog[extent_index], sizeof(Bit32u)); - } - - return written; -} - - -/*** growing_image_t function definitions ***/ - -growing_image_t::growing_image_t(Bit64u _size) -{ - redolog = new redolog_t(); - size = _size; -} - -int growing_image_t::open (const char* pathname) -{ - int filedes = redolog->open(pathname,REDOLOG_SUBTYPE_GROWING,size); - BX_INFO(("'growing' disk opened, growing file is '%s'", pathname)); - return filedes; -} - -void growing_image_t::close () -{ - redolog->close(); -} - -off_t growing_image_t::lseek (off_t offset, int whence) -{ - return redolog->lseek(offset, whence); -} - -ssize_t growing_image_t::read (void* buf, size_t count) -{ - memset(buf, 0, count); - redolog->read((char*) buf, count); - return count; -} - -ssize_t growing_image_t::write (const void* buf, size_t count) -{ - return redolog->write((char*) buf, count); -} - - -/*** undoable_image_t function definitions ***/ - -undoable_image_t::undoable_image_t(Bit64u _size, const char* _redolog_name) -{ - redolog = new redolog_t(); - ro_disk = new default_image_t(); - size = _size; - redolog_name = NULL; - if (_redolog_name != NULL) { - if (strcmp(_redolog_name,"") != 0) { - redolog_name = strdup(_redolog_name); - } - } -} - -int undoable_image_t::open (const char* pathname) -{ - char *logname=NULL; - - if (ro_disk->open(pathname, O_RDONLY)<0) - return -1; - - // if redolog name was set - if ( redolog_name != NULL) { - if ( strcmp(redolog_name, "") != 0 ) { - logname = (char*)malloc(strlen(redolog_name) + 1); - strcpy (logname, redolog_name); - } - } - - // Otherwise we make up the redolog filename from the pathname - if ( logname == NULL) { - logname = (char*)malloc(strlen(pathname) + UNDOABLE_REDOLOG_EXTENSION_LENGTH + 1); - sprintf (logname, "%s%s", pathname, UNDOABLE_REDOLOG_EXTENSION); - } - - if (redolog->open(logname,REDOLOG_SUBTYPE_UNDOABLE,size) < 0) - { - if (redolog->create(logname, REDOLOG_SUBTYPE_UNDOABLE, size) < 0) - { - BX_PANIC(("Can't open or create redolog '%s'",logname)); - return -1; - } - } - - BX_INFO(("'undoable' disk opened: ro-file is '%s', redolog is '%s'", pathname, logname)); - free(logname); - - return 0; -} - -void undoable_image_t::close () -{ - redolog->close(); - ro_disk->close(); - - if (redolog_name!=NULL) - free(redolog_name); -} - -off_t undoable_image_t::lseek (off_t offset, int whence) -{ - redolog->lseek(offset, whence); - return ro_disk->lseek(offset, whence); -} - -ssize_t undoable_image_t::read (void* buf, size_t count) -{ - // This should be fixed if count != 512 - if ((size_t)redolog->read((char*) buf, count) != count) - return ro_disk->read((char*) buf, count); - else - return count; -} - -ssize_t undoable_image_t::write (const void* buf, size_t count) -{ - return redolog->write((char*) buf, count); -} - - -/*** volatile_image_t function definitions ***/ - -volatile_image_t::volatile_image_t(Bit64u _size, const char* _redolog_name) -{ - redolog = new redolog_t(); - ro_disk = new default_image_t(); - size = _size; - redolog_temp = NULL; - redolog_name = NULL; - if (_redolog_name != NULL) { - if (strcmp(_redolog_name,"") != 0) { - redolog_name = strdup(_redolog_name); - } - } -} - -int volatile_image_t::open (const char* pathname) -{ - int filedes; - const char *logname=NULL; - - if (ro_disk->open(pathname, O_RDONLY)<0) - return -1; - - // if redolog name was set - if ( redolog_name != NULL) { - if ( strcmp(redolog_name, "") != 0 ) { - logname = redolog_name; - } - } - - // otherwise use pathname as template - if (logname == NULL) { - logname = pathname; - } - - redolog_temp = (char*)malloc(strlen(logname) + VOLATILE_REDOLOG_EXTENSION_LENGTH + 1); - sprintf (redolog_temp, "%s%s", logname, VOLATILE_REDOLOG_EXTENSION); - - filedes = mkstemp (redolog_temp); - - if (filedes < 0) - { - BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp)); - return -1; - } - if (redolog->create(filedes, REDOLOG_SUBTYPE_VOLATILE, size) < 0) - { - BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp)); - return -1; - } - -#if (!defined(WIN32)) && !BX_WITH_MACOS - // on unix it is legal to delete an open file - unlink(redolog_temp); -#endif - - BX_INFO(("'volatile' disk opened: ro-file is '%s', redolog is '%s'", pathname, redolog_temp)); - - return 0; -} - -void volatile_image_t::close () -{ - redolog->close(); - ro_disk->close(); - -#if defined(WIN32) || BX_WITH_MACOS - // on non-unix we have to wait till the file is closed to delete it - unlink(redolog_temp); -#endif - if (redolog_temp!=NULL) - free(redolog_temp); - - if (redolog_name!=NULL) - free(redolog_name); -} - -off_t volatile_image_t::lseek (off_t offset, int whence) -{ - redolog->lseek(offset, whence); - return ro_disk->lseek(offset, whence); -} - -ssize_t volatile_image_t::read (void* buf, size_t count) -{ - // This should be fixed if count != 512 - if ((size_t)redolog->read((char*) buf, count) != count) - return ro_disk->read((char*) buf, count); - else - return count; -} - -ssize_t volatile_image_t::write (const void* buf, size_t count) -{ - return redolog->write((char*) buf, count); -} - -#if BX_COMPRESSED_HD_SUPPORT - -/*** z_ro_image_t function definitions ***/ - -z_ro_image_t::z_ro_image_t() -{ - offset = (off_t)0; -} - -int z_ro_image_t::open (const char* pathname) -{ - fd = ::open(pathname, O_RDONLY -#ifdef O_BINARY - | O_BINARY -#endif - ); - - if(fd < 0) - { - BX_PANIC(("Could not open '%s' file", pathname)); - return fd; - } - - gzfile = gzdopen(fd, "rb"); -} - -void z_ro_image_t::close () -{ - if (fd > -1) { - gzclose(gzfile); - // ::close(fd); - } -} - -off_t z_ro_image_t::lseek (off_t _offset, int whence) -{ - // Only SEEK_SET supported - if (whence != SEEK_SET) - { - BX_PANIC(("lseek on compressed images : only SEEK_SET supported")); - } - - // Seeking is expensive on compressed files, so we do it - // only when necessary, at the latest moment - offset = _offset; - - return offset; -} - -ssize_t z_ro_image_t::read (void* buf, size_t count) -{ - gzseek(gzfile, offset, SEEK_SET); - return gzread(gzfile, buf, count); -} - -ssize_t z_ro_image_t::write (const void* buf, size_t count) -{ - BX_PANIC(("z_ro_image: write not supported")); - return 0; -} - - -/*** z_undoable_image_t function definitions ***/ - -z_undoable_image_t::z_undoable_image_t(Bit64u _size, const char* _redolog_name) -{ - redolog = new redolog_t(); - ro_disk = new z_ro_image_t(); - size = _size; - - redolog_name = NULL; - if (_redolog_name != NULL) { - if (strcmp(_redolog_name,"") != 0) { - redolog_name = strdup(_redolog_name); - } - } -} - -int z_undoable_image_t::open (const char* pathname) -{ - char *logname=NULL; - - if (ro_disk->open(pathname)<0) - return -1; - - // If redolog name was set - if ( redolog_name != NULL) { - if ( strcmp(redolog_name, "") != 0) { - logname = (char*)malloc(strlen(redolog_name) + 1); - strcpy (logname, redolog_name); - } - } - - // Otherwise we make up the redolog filename from the pathname - if ( logname == NULL) { - logname = (char*)malloc(strlen(pathname) + UNDOABLE_REDOLOG_EXTENSION_LENGTH + 1); - sprintf (logname, "%s%s", pathname, UNDOABLE_REDOLOG_EXTENSION); - } - - if (redolog->open(logname,REDOLOG_SUBTYPE_UNDOABLE,size) < 0) - { - if (redolog->create(logname, REDOLOG_SUBTYPE_UNDOABLE, size) < 0) - { - BX_PANIC(("Can't open or create redolog '%s'",logname)); - return -1; - } - } - - BX_INFO(("'z-undoable' disk opened, z-ro-file is '%s', redolog is '%s'", pathname, logname)); - free(logname); - - return 0; -} - -void z_undoable_image_t::close () -{ - redolog->close(); - ro_disk->close(); - - if (redolog_name!=NULL) - free(redolog_name); -} - -off_t z_undoable_image_t::lseek (off_t offset, int whence) -{ - redolog->lseek(offset, whence); - return ro_disk->lseek(offset, whence); -} - -ssize_t z_undoable_image_t::read (void* buf, size_t count) -{ - // This should be fixed if count != 512 - if (redolog->read((char*) buf, count) != count) - return ro_disk->read((char*) buf, count); - else - return count; -} - -ssize_t z_undoable_image_t::write (const void* buf, size_t count) -{ - return redolog->write((char*) buf, count); -} - - -/*** z_volatile_image_t function definitions ***/ - -z_volatile_image_t::z_volatile_image_t(Bit64u _size, const char* _redolog_name) -{ - redolog = new redolog_t(); - ro_disk = new z_ro_image_t(); - size = _size; - - redolog_temp = NULL; - redolog_name = NULL; - if (_redolog_name != NULL) { - if (strcmp(_redolog_name,"") != 0) { - redolog_name = strdup(_redolog_name); - } - } -} - -int z_volatile_image_t::open (const char* pathname) -{ - int filedes; - const char *logname=NULL; - - if (ro_disk->open(pathname)<0) - return -1; - - // if redolog name was set - if ( redolog_name != NULL) { - if ( strcmp(redolog_name, "") !=0 ) { - logname = redolog_name; - } - } - - // otherwise use pathname as template - if (logname == NULL) { - logname = pathname; - } - - redolog_temp = (char*)malloc(strlen(logname) + VOLATILE_REDOLOG_EXTENSION_LENGTH + 1); - sprintf (redolog_temp, "%s%s", logname, VOLATILE_REDOLOG_EXTENSION); - - filedes = mkstemp (redolog_temp); - - if (filedes < 0) - { - BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp)); - return -1; - } - if (redolog->create(filedes, REDOLOG_SUBTYPE_VOLATILE, size) < 0) - { - BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp)); - return -1; - } - -#if (!defined(WIN32)) && !BX_WITH_MACOS - // on unix it is legal to delete an open file - unlink(redolog_temp); -#endif - - BX_INFO(("'z-volatile' disk opened: z-ro-file is '%s', redolog is '%s'", pathname, redolog_temp)); - - return 0; -} - -void z_volatile_image_t::close () -{ - redolog->close(); - ro_disk->close(); - -#if defined(WIN32) || BX_WITH_MACOS - // on non-unix we have to wait till the file is closed to delete it - unlink(redolog_temp); -#endif - - if (redolog_temp!=NULL) - free(redolog_temp); - - if (redolog_name!=NULL) - free(redolog_name); -} - -off_t z_volatile_image_t::lseek (off_t offset, int whence) -{ - redolog->lseek(offset, whence); - return ro_disk->lseek(offset, whence); -} - -ssize_t z_volatile_image_t::read (void* buf, size_t count) -{ - // This should be fixed if count != 512 - if (redolog->read((char*) buf, count) != count) - return ro_disk->read((char*) buf, count); - else - return count; -} - -ssize_t z_volatile_image_t::write (const void* buf, size_t count) -{ - return redolog->write((char*) buf, count); -} - - -#endif diff --git a/tools/ioemu/iodev/harddrv.h b/tools/ioemu/iodev/harddrv.h deleted file mode 100644 index 9320e614d5..0000000000 --- a/tools/ioemu/iodev/harddrv.h +++ /dev/null @@ -1,765 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: harddrv.h,v 1.22.2.1 2004/02/06 22:14:36 danielg4 Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// SPARSE IMAGES HEADER -#define SPARSE_HEADER_MAGIC (0x02468ace) -#define SPARSE_HEADER_VERSION 1 -#define SPARSE_HEADER_SIZE (256) // Plenty of room for later -#define SPARSE_PAGE_NOT_ALLOCATED (0xffffffff) - - typedef struct - { - uint32 magic; - uint32 version; - uint32 pagesize; - uint32 numpages; - - uint32 padding[60]; - } sparse_header_t; - -#define STANDARD_HEADER_MAGIC "Bochs Virtual HD Image" -#define STANDARD_HEADER_VERSION (0x00010000) -#define STANDARD_HEADER_SIZE (512) - - - // WARNING : headers are kept in x86 (little) endianness - typedef struct - { - Bit8u magic[32]; - Bit8u type[16]; - Bit8u subtype[16]; - Bit32u version; - Bit32u header; - } standard_header_t; - -#define REDOLOG_TYPE "Redolog" -#define REDOLOG_SUBTYPE_UNDOABLE "Undoable" -#define REDOLOG_SUBTYPE_VOLATILE "Volatile" -#define REDOLOG_SUBTYPE_GROWING "Growing" -// #define REDOLOG_SUBTYPE_Z_UNDOABLE "z-Undoable" -// #define REDOLOG_SUBTYPE_Z_VOLATILE "z-Volatile" - -#define REDOLOG_PAGE_NOT_ALLOCATED (0xffffffff) - -#define UNDOABLE_REDOLOG_EXTENSION ".redolog" -#define UNDOABLE_REDOLOG_EXTENSION_LENGTH (strlen(UNDOABLE_REDOLOG_EXTENSION)) -#define VOLATILE_REDOLOG_EXTENSION ".XXXXXX" -#define VOLATILE_REDOLOG_EXTENSION_LENGTH (strlen(VOLATILE_REDOLOG_EXTENSION)) - - typedef struct - { - // the fields in the header are kept in little endian - Bit32u catalog; // #entries in the catalog - Bit32u bitmap; // bitmap size in bytes - Bit32u extent; // extent size in bytes - Bit64u disk; // disk size in bytes - } redolog_specific_header_t; - - typedef struct - { - standard_header_t standard; - redolog_specific_header_t specific; - - Bit8u padding[STANDARD_HEADER_SIZE - (sizeof (standard_header_t) + sizeof (redolog_specific_header_t))]; - } redolog_header_t; - -// htod : convert host to disk (little) endianness -// dtoh : convert disk (little) to host endianness -#if defined (BX_LITTLE_ENDIAN) -#define htod32(val) (val) -#define dtoh32(val) (val) -#define htod64(val) (val) -#define dtoh64(val) (val) -#else -#define htod32(val) ( (((val)&0xff000000)>>24) | (((val)&0xff0000)>>8) | (((val)&0xff00)<<8) | (((val)&0xff)<<24) ) -#define dtoh32(val) htod32(val) -#define htod64(val) ( (((val)&0xff00000000000000LL)>>56) | (((val)&0xff000000000000LL)>>40) | (((val)&0xff0000000000LL)>>24) | (((val)&0xff00000000LL)>>8) | (((val)&0xff000000LL)<<8) | (((val)&0xff0000LL)<<24) | (((val)&0xff00LL)<<40) | (((val)&0xffLL)<<56) ) -#define dtoh64(val) htod64(val) -#endif - -#ifndef INCLUDE_ONLY_HD_HEADERS - -typedef enum _sense { - SENSE_NONE = 0, SENSE_NOT_READY = 2, SENSE_ILLEGAL_REQUEST = 5, - SENSE_UNIT_ATTENTION = 6 -} sense_t; - -typedef enum _asc { - ASC_INV_FIELD_IN_CMD_PACKET = 0x24, - ASC_MEDIUM_NOT_PRESENT = 0x3a, - ASC_SAVING_PARAMETERS_NOT_SUPPORTED = 0x39, - ASC_LOGICAL_BLOCK_OOR = 0x21 -} asc_t; - -class LOWLEVEL_CDROM; - -class device_image_t -{ - public: - // Open a image. Returns non-negative if successful. - virtual int open (const char* pathname) = 0; - - // Close the image. - virtual void close () = 0; - - // Position ourselves. Return the resulting offset from the - // beginning of the file. - virtual off_t lseek (off_t offset, int whence) = 0; - - // Read count bytes to the buffer buf. Return the number of - // bytes read (count). - virtual ssize_t read (void* buf, size_t count) = 0; - - // Write count bytes from buf. Return the number of bytes - // written (count). - virtual ssize_t write (const void* buf, size_t count) = 0; - - unsigned cylinders; - unsigned heads; - unsigned sectors; -}; - -// FLAT MODE -class default_image_t : public device_image_t -{ - public: - // Open a image. Returns non-negative if successful. - int open (const char* pathname); - - // Open an image with specific flags. Returns non-negative if successful. - int open (const char* pathname, int flags); - - // Close the image. - void close (); - - // Position ourselves. Return the resulting offset from the - // beginning of the file. - off_t lseek (off_t offset, int whence); - - // Read count bytes to the buffer buf. Return the number of - // bytes read (count). - ssize_t read (void* buf, size_t count); - - // Write count bytes from buf. Return the number of bytes - // written (count). - ssize_t write (const void* buf, size_t count); - - private: - int fd; - -}; - -// CONCAT MODE -class concat_image_t : public device_image_t -{ - public: - // Default constructor - concat_image_t(); - - // Open a image. Returns non-negative if successful. - int open (const char* pathname); - - // Close the image. - void close (); - - // Position ourselves. Return the resulting offset from the - // beginning of the file. - off_t lseek (off_t offset, int whence); - - // Read count bytes to the buffer buf. Return the number of - // bytes read (count). - ssize_t read (void* buf, size_t count); - - // Write count bytes from buf. Return the number of bytes - // written (count). - ssize_t write (const void* buf, size_t count); - - private: -#define BX_CONCAT_MAX_IMAGES 8 - int fd_table[BX_CONCAT_MAX_IMAGES]; - off_t start_offset_table[BX_CONCAT_MAX_IMAGES]; - off_t length_table[BX_CONCAT_MAX_IMAGES]; - void increment_string (char *str); - int maxfd; // number of entries in tables that are valid - - // notice if anyone does sequential read or write without seek in between. - // This can be supported pretty easily, but needs additional checks. - // 0=something other than seek was last operation - // 1=seek was last operation - int seek_was_last_op; - - // the following variables tell which partial image file to use for - // the next read and write. - int index; // index into table - int fd; // fd to use for reads and writes - off_t thismin, thismax; // byte offset boundary of this image -}; - -// SPARSE MODE -class sparse_image_t : public device_image_t -{ - -// Format of a sparse file: -// 256 byte header, containing details such as page size and number of pages -// Page indirection table, mapping virtual pages to physical pages within file -// Physical pages till end of file - - public: - // Default constructor - sparse_image_t(); - - // Open a image. Returns non-negative if successful. - int open (const char* pathname); - - // Close the image. - void close (); - - // Position ourselves. Return the resulting offset from the - // beginning of the file. - off_t lseek (off_t offset, int whence); - - // Read count bytes to the buffer buf. Return the number of - // bytes read (count). - ssize_t read (void* buf, size_t count); - - // Write count bytes from buf. Return the number of bytes - // written (count). - ssize_t write (const void* buf, size_t count); - - private: - int fd; - -#ifdef _POSIX_MAPPED_FILES - void * mmap_header; - size_t mmap_length; - size_t system_pagesize_mask; -#endif - uint32 * pagetable; - - // Header is written to disk in little-endian (x86) format - // Thus needs to be converted on big-endian systems before read - // The pagetable is also kept little endian - - sparse_header_t header; - - uint32 pagesize; - int pagesize_shift; - uint32 pagesize_mask; - - off_t data_start; - off_t underlying_filesize; - - char * pathname; - - off_t position; - - uint32 position_virtual_page; - uint32 position_physical_page; - uint32 position_page_offset; - - off_t underlying_current_filepos; - - off_t total_size; - - void panic(const char * message); - off_t -#ifndef PARANOID - sparse_image_t:: -#endif - get_physical_offset(); - void -#ifndef PARANOID - sparse_image_t:: -#endif - set_virtual_page(uint32 new_virtual_page); - void read_header(); - ssize_t read_page_fragment(uint32 read_virtual_page, uint32 read_page_offset, size_t read_size, void * buf); - - sparse_image_t * parent_image; -}; - -#if EXTERNAL_DISK_SIMULATOR -#include "external-disk-simulator.h" -#endif - -#if DLL_HD_SUPPORT -class dll_image_t : public device_image_t -{ - public: - // Open a image. Returns non-negative if successful. - int open (const char* pathname); - - // Close the image. - void close (); - - // Position ourselves. Return the resulting offset from the - // beginning of the file. - off_t lseek (off_t offset, int whence); - - // Read count bytes to the buffer buf. Return the number of - // bytes read (count). - ssize_t read (void* buf, size_t count); - - // Write count bytes from buf. Return the number of bytes - // written (count). - ssize_t write (const void* buf, size_t count); - - private: - int vunit,vblk; - -}; -#endif - -// REDOLOG class -class redolog_t -{ - public: - redolog_t(); - int make_header (const char* type, Bit64u size); - int create (const char* filename, const char* type, Bit64u size); - int create (int filedes, const char* type, Bit64u size); - int open (const char* filename, const char* type, Bit64u size); - void close (); - - off_t lseek (off_t offset, int whence); - ssize_t read (void* buf, size_t count); - ssize_t write (const void* buf, size_t count); - - private: - void print_header(); - int fd; - redolog_header_t header; // Header is kept in x86 (little) endianness - Bit32u *catalog; - Bit8u *bitmap; - Bit32u extent_index; - Bit32u extent_offset; - Bit32u extent_next; - - Bit32u bitmap_blocs; - Bit32u extent_blocs; -}; - -// GROWING MODE -class growing_image_t : public device_image_t -{ - public: - // Contructor - growing_image_t(Bit64u size); - - // Open a image. Returns non-negative if successful. - int open (const char* pathname); - - // Close the image. - void close (); - - // Position ourselves. Return the resulting offset from the - // beginning of the file. - off_t lseek (off_t offset, int whence); - - // Read count bytes to the buffer buf. Return the number of - // bytes read (count). - ssize_t read (void* buf, size_t count); - - // Write count bytes from buf. Return the number of bytes - // written (count). - ssize_t write (const void* buf, size_t count); - - private: - redolog_t *redolog; - Bit64u size; -}; - -// UNDOABLE MODE -class undoable_image_t : public device_image_t -{ - public: - // Contructor - undoable_image_t(Bit64u size, const char* redolog_name); - - // Open a image. Returns non-negative if successful. - int open (const char* pathname); - - // Close the image. - void close (); - - // Position ourselves. Return the resulting offset from the - // beginning of the file. - off_t lseek (off_t offset, int whence); - - // Read count bytes to the buffer buf. Return the number of - // bytes read (count). - ssize_t read (void* buf, size_t count); - - // Write count bytes from buf. Return the number of bytes - // written (count). - ssize_t write (const void* buf, size_t count); - - private: - redolog_t *redolog; // Redolog instance - default_image_t *ro_disk; // Read-only flat disk instance - Bit64u size; - char *redolog_name; // Redolog name -}; - - -// VOLATILE MODE -class volatile_image_t : public device_image_t -{ - public: - // Contructor - volatile_image_t(Bit64u size, const char* redolog_name); - - // Open a image. Returns non-negative if successful. - int open (const char* pathname); - - // Close the image. - void close (); - - // Position ourselves. Return the resulting offset from the - // beginning of the file. - off_t lseek (off_t offset, int whence); - - // Read count bytes to the buffer buf. Return the number of - // bytes read (count). - ssize_t read (void* buf, size_t count); - - // Write count bytes from buf. Return the number of bytes - // written (count). - ssize_t write (const void* buf, size_t count); - - private: - redolog_t *redolog; // Redolog instance - default_image_t *ro_disk; // Read-only flat disk instance - Bit64u size; - char *redolog_name; // Redolog name - char *redolog_temp; // Redolog temporary file name -}; - - -#if BX_COMPRESSED_HD_SUPPORT - -#include - - -// Default compressed READ-ONLY image class -class z_ro_image_t : public device_image_t -{ - public: - // Contructor - z_ro_image_t(); - - // Open a image. Returns non-negative if successful. - int open (const char* pathname); - - // Close the image. - void close (); - - // Position ourselves. Return the resulting offset from the - // beginning of the file. - off_t lseek (off_t offset, int whence); - - // Read count bytes to the buffer buf. Return the number of - // bytes read (count). - ssize_t read (void* buf, size_t count); - - // Write count bytes from buf. Return the number of bytes - // written (count). - ssize_t write (const void* buf, size_t count); - - private: - off_t offset; - int fd; - gzFile gzfile; - -}; - -// Z-UNDOABLE MODE -class z_undoable_image_t : public device_image_t -{ - public: - // Contructor - z_undoable_image_t(Bit64u size, const char* redolog_name); - - // Open a image. Returns non-negative if successful. - int open (const char* pathname); - - // Close the image. - void close (); - - // Position ourselves. Return the resulting offset from the - // beginning of the file. - off_t lseek (off_t offset, int whence); - - // Read count bytes to the buffer buf. Return the number of - // bytes read (count). - ssize_t read (void* buf, size_t count); - - // Write count bytes from buf. Return the number of bytes - // written (count). - ssize_t write (const void* buf, size_t count); - - private: - redolog_t *redolog; // Redolog instance - z_ro_image_t *ro_disk; // Read-only compressed flat disk instance - Bit64u size; - char *redolog_name; // Redolog name -}; - -// Z-VOLATILE MODE -class z_volatile_image_t : public device_image_t -{ - public: - // Contructor - z_volatile_image_t(Bit64u size, const char* redolog_name); - - // Open a image. Returns non-negative if successful. - int open (const char* pathname); - - // Close the image. - void close (); - - // Position ourselves. Return the resulting offset from the - // beginning of the file. - off_t lseek (off_t offset, int whence); - - // Read count bytes to the buffer buf. Return the number of - // bytes read (count). - ssize_t read (void* buf, size_t count); - - // Write count bytes from buf. Return the number of bytes - // written (count). - ssize_t write (const void* buf, size_t count); - - private: - redolog_t *redolog; // Redolog instance - z_ro_image_t *ro_disk; // Read-only compressed flat disk instance - Bit64u size; - char *redolog_name; // Redolog name - char *redolog_temp; // Redolog temporary file name -}; - -#endif - - -typedef struct { - struct { - bx_bool busy; - bx_bool drive_ready; - bx_bool write_fault; - bx_bool seek_complete; - bx_bool drq; - bx_bool corrected_data; - bx_bool index_pulse; - unsigned index_pulse_count; - bx_bool err; - } status; - Bit8u error_register; - Bit8u head_no; - union { - Bit8u sector_count; - struct { -#ifdef BX_LITTLE_ENDIAN - unsigned c_d : 1; - unsigned i_o : 1; - unsigned rel : 1; - unsigned tag : 5; -#else /* BX_BIG_ENDIAN */ - unsigned tag : 5; - unsigned rel : 1; - unsigned i_o : 1; - unsigned c_d : 1; -#endif - } interrupt_reason; - }; - Bit8u sector_no; - union { - Bit16u cylinder_no; - Bit16u byte_count; - }; - Bit8u buffer[2048]; - Bit32u buffer_index; - Bit32u drq_index; - Bit8u current_command; - Bit8u sectors_per_block; - Bit8u lba_mode; - struct { - bx_bool reset; // 0=normal, 1=reset controller - bx_bool disable_irq; // 0=allow irq, 1=disable irq - } control; - Bit8u reset_in_progress; - Bit8u features; - } controller_t; - -struct sense_info_t { - sense_t sense_key; - struct { - Bit8u arr[4]; - } information; - struct { - Bit8u arr[4]; - } specific_inf; - struct { - Bit8u arr[3]; - } key_spec; - Bit8u fruc; - Bit8u asc; - Bit8u ascq; -}; - -struct error_recovery_t { - unsigned char data[8]; - - error_recovery_t (); -}; - -uint16 read_16bit(const uint8* buf) BX_CPP_AttrRegparmN(1); -uint32 read_32bit(const uint8* buf) BX_CPP_AttrRegparmN(1); - - -#ifdef LOWLEVEL_CDROM -# include "cdrom.h" -#endif - - -struct cdrom_t -{ - bx_bool ready; - bx_bool locked; -#ifdef LOWLEVEL_CDROM - LOWLEVEL_CDROM* cd; -#endif - uint32 capacity; - int next_lba; - int remaining_blocks; - struct currentStruct { - error_recovery_t error_recovery; - } current; -}; - -struct atapi_t -{ - uint8 command; - int drq_bytes; - int total_bytes_remaining; -}; - -#if BX_USE_HD_SMF -# define BX_HD_SMF static -# define BX_HD_THIS theHardDrive-> -#else -# define BX_HD_SMF -# define BX_HD_THIS this-> -#endif - -typedef enum { - IDE_NONE, IDE_DISK, IDE_CDROM -} device_type_t; - -class bx_hard_drive_c : public bx_hard_drive_stub_c { -public: - - bx_hard_drive_c(void); - virtual ~bx_hard_drive_c(void); - virtual void close_harddrive(void); - virtual void init(); - virtual void reset(unsigned type); - virtual Bit32u get_device_handle(Bit8u channel, Bit8u device); - virtual Bit32u get_first_cd_handle(void); - virtual unsigned get_cd_media_status(Bit32u handle); - virtual unsigned set_cd_media_status(Bit32u handle, unsigned status); - - virtual Bit32u virt_read_handler(Bit32u address, unsigned io_len) { - return read_handler (this, address, io_len); - } - virtual void virt_write_handler(Bit32u address, - Bit32u value, unsigned io_len) - { - write_handler(this, address, value, io_len); - } -#if !BX_USE_HD_SMF - Bit32u read(Bit32u address, unsigned io_len); - void write(Bit32u address, Bit32u value, unsigned io_len); -#endif - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); - -private: - - BX_HD_SMF bx_bool calculate_logical_address(Bit8u channel, off_t *sector) BX_CPP_AttrRegparmN(2); - BX_HD_SMF void increment_address(Bit8u channel) BX_CPP_AttrRegparmN(1); - BX_HD_SMF void identify_drive(Bit8u channel); - BX_HD_SMF void identify_ATAPI_drive(Bit8u channel); - BX_HD_SMF void command_aborted(Bit8u channel, unsigned command); - - BX_HD_SMF void init_send_atapi_command(Bit8u channel, Bit8u command, int req_length, int alloc_length, bool lazy = false) BX_CPP_AttrRegparmN(3); - BX_HD_SMF void ready_to_send_atapi(Bit8u channel) BX_CPP_AttrRegparmN(1); - BX_HD_SMF void raise_interrupt(Bit8u channel) BX_CPP_AttrRegparmN(1); - BX_HD_SMF void atapi_cmd_error(Bit8u channel, sense_t sense_key, asc_t asc); - BX_HD_SMF void init_mode_sense_single(Bit8u channel, const void* src, int size); - BX_HD_SMF void atapi_cmd_nop(Bit8u channel) BX_CPP_AttrRegparmN(1); - - // FIXME: - // For each ATA channel we should have one controller struct - // and an array of two drive structs - struct channel_t { - struct drive_t { - device_image_t* hard_drive; - device_type_t device_type; - // 512 byte buffer for ID drive command - // These words are stored in native word endian format, as - // they are fetched and returned via a return(), so - // there's no need to keep them in x86 endian format. - Bit16u id_drive[256]; - - controller_t controller; - cdrom_t cdrom; - sense_info_t sense; - atapi_t atapi; - - Bit8u model_no[41]; - } drives[2]; - unsigned drive_select; - - Bit16u ioaddr1; - Bit16u ioaddr2; - Bit8u irq; - - } channels[BX_MAX_ATA_CHANNEL]; - -#if BX_PDC20230C_VLBIDE_SUPPORT -// pdc20630c is only available for 1st ata channel - struct pdc20630c_t { - bx_bool prog_mode; - Bit8u prog_count; - Bit32u p1f3_value; - Bit32u p1f4_value; - } pdc20230c; -#endif - - }; -#endif // INCLUDE_ONLY_SPARSE_HEADER - diff --git a/tools/ioemu/iodev/ioapic.cc b/tools/ioemu/iodev/ioapic.cc deleted file mode 100644 index 8aaf67f848..0000000000 --- a/tools/ioemu/iodev/ioapic.cc +++ /dev/null @@ -1,175 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: ioapic.cc,v 1.11 2002/11/19 05:47:45 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -#include -#include "bochs.h" -#if BX_SUPPORT_APIC - -class bx_ioapic_c bx_ioapic; -#define LOG_THIS bx_ioapic. - -void -bx_io_redirect_entry_t::parse_value () -{ - dest = (value >> 56) & 0xff; - masked = (value >> 16) & 1; - trig_mode = (value >> 15) & 1; - remote_irr = (value >> 14) & 1; - polarity = (value >> 13) & 1; - //delivery_status = (value >> 12) & 1; - delivery_status = 0; // always say the message has gone through - dest_mode = (value >> 11) & 1; - delivery_mode = (value >> 8) & 7; - vector = (value >> 0) & 0xff; -} - -void -bx_io_redirect_entry_t::sprintf_self (char *buf) -{ - sprintf (buf, "dest=%02x, masked=%d, trig_mode=%d, remote_irr=%d, polarity=%d, delivery_status=%d, dest_mode=%d, delivery_mode=%d, vector=%02x", dest, masked, trig_mode, remote_irr, polarity, delivery_status, dest_mode, delivery_mode, vector); -} - -bx_ioapic_c::bx_ioapic_c () - : bx_generic_apic_c () -{ - put("IOAP"); - settype(IOAPICLOG); -} - -bx_ioapic_c::~bx_ioapic_c () { -} - -void -bx_ioapic_c::init () -{ - bx_generic_apic_c::init (); - BX_DEBUG(("initializing I/O APIC")); - base_addr = 0xfec00000; - ioregsel = 0; - // all interrupts masked - for (int i=0; i> 1; - if (index >= 0 && index < BX_IOAPIC_NUM_PINS) { - bx_io_redirect_entry_t *entry = ioredtbl + index; - *data = (ioregsel&1) ? entry->get_odd_word() : entry->get_even_word (); - return; - } - BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x", ioregsel)); - } -} - -void -bx_ioapic_c::write(Bit32u address, Bit32u *value, unsigned len) -{ - BX_DEBUG(("IOAPIC: write addr=%08x, data=%08x, len=%d", address, *value, len)); - address &= 0xff; - if (address == 0x00) { - ioregsel = *value; - return; - } else if (address != 0x10) { - BX_PANIC(("IOAPIC: write to unsupported address")); - } - // only reached when writing data register - switch (ioregsel) { - case 0x00: // set APIC ID - { - Bit8u newid = (*value >> 24) & 0xf; - BX_INFO(("IOAPIC: setting id to 0x%x", newid)); - set_id (newid); - return; - } - case 0x01: // version - case 0x02: // arbitration id - BX_INFO(("IOAPIC: could not write, IOREGSEL=0x%02x", ioregsel)); - return; - default: - int index = (ioregsel - 0x10) >> 1; - if (index >= 0 && index < BX_IOAPIC_NUM_PINS) { - bx_io_redirect_entry_t *entry = ioredtbl + index; - if (ioregsel&1) - entry->set_odd_word (*value); - else - entry->set_even_word (*value); - char buf[1024]; - entry->sprintf_self (buf); - BX_DEBUG(("IOAPIC: now entry[%d] is %s", index, buf)); - service_ioapic (); - return; - } - BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x", ioregsel)); - } -} - -void bx_ioapic_c::trigger_irq (unsigned vector, unsigned from) -{ - BX_DEBUG(("IOAPIC: received interrupt %d", vector)); - if (vector >= 0 && vector < BX_IOAPIC_NUM_PINS) { - Bit32u bit = 1<masked) { - // clear irr bit and deliver - bx_bool done = deliver (entry->dest, entry->dest_mode, entry->delivery_mode, entry->vector, entry->polarity, entry->trig_mode); - if (done) irr &= ~(1<>32) & 0xffffffff; } - void set_even_word (Bit32u even) { - // keep high 32 bits of value, replace low 32 - value = ((value >> 32) << 32) | (even & 0xffffffff); - parse_value (); - } - void set_odd_word (Bit32u odd) { - // keep low 32 bits of value, replace high 32 - value = (((Bit64u)odd & 0xffffffff) << 32) | (value & 0xffffffff); - parse_value (); - } - void parse_value (); - // parse_value sets the value and all the fields below. Do not change - // these fields except by calling parse_value. - Bit8u dest, masked, trig_mode, remote_irr, polarity, delivery_status, dest_mode, delivery_mode, vector; - void sprintf_self (char *buf); -}; - -class bx_ioapic_c : public bx_generic_apic_c { - Bit32u ioregsel; // selects between various registers - // interrupt request bitmask, not visible from the outside. Bits in the - // irr are set when trigger_irq is called, and cleared when the interrupt - // is delivered to the processor. If an interrupt is masked, the irr - // will still be set but delivery will not occur until it is unmasked. - // It's not clear if this is how the real device works. - Bit32u irr; -public: - bx_io_redirect_entry_t ioredtbl[BX_IOAPIC_NUM_PINS]; // table of redirections - bx_ioapic_c (); - ~bx_ioapic_c (); - virtual void init (); - virtual void reset (unsigned type); - virtual void read_aligned(Bit32u address, Bit32u *data, unsigned len); - virtual void write(Bit32u address, Bit32u *value, unsigned len); - void trigger_irq (unsigned num, unsigned from); - void untrigger_irq (unsigned num, unsigned from); - void service_ioapic (); - virtual bx_bool match_logical_addr (Bit8u address) { return false; } - virtual bx_bool is_local_apic () { return false; } - virtual bx_apic_type_t get_type () { return APIC_TYPE_IOAPIC; } -}; diff --git a/tools/ioemu/iodev/iodebug.cc b/tools/ioemu/iodev/iodebug.cc deleted file mode 100644 index ca2314ede6..0000000000 --- a/tools/ioemu/iodev/iodebug.cc +++ /dev/null @@ -1,354 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: iodebug.cc,v 1.15 2002/11/19 05:47:45 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -#include "bochs.h" -#if BX_IODEBUG_SUPPORT - - - -bx_iodebug_c bx_iodebug; -bx_iodebug_c *bx_iodebug_ptr; - - struct bx_iodebug_s_type { - bx_bool enabled; - unsigned int register_select; - Bit32u registers[2]; - Bit32u monitored_mem_areas_start[BX_IODEBUG_MAX_AREAS]; - Bit32u monitored_mem_areas_end[BX_IODEBUG_MAX_AREAS]; - } bx_iodebug_s; - - - - -// Constructor -bx_iodebug_c::bx_iodebug_c( void ) -{ - put("IODEBUG"); - settype(IODEBUGLOG); - -} - - - - - -// Destructor -bx_iodebug_c::~bx_iodebug_c( void ) -{ -} - - - - - -void bx_iodebug_c::init(void) -{ - int i; - - DEV_register_ioread_handler(this, read_handler, 0x8A00,"BOCHS IODEBUG", 7); - DEV_register_iowrite_handler(this, write_handler, 0x8A00,"BOCHS IODEBUG", 7); - DEV_register_iowrite_handler(this, write_handler, 0x8A01,"BOCHS IODEBUG", 7); -// fprintf( stderr, "IODEBUG initialized\n"); - - bx_iodebug_s.enabled = 0; - bx_iodebug_s.register_select = 0; - for(i=0;iread(addr, io_len) ); -} - - - - - - -Bit32u bx_iodebug_c::read( Bit32u addr, unsigned io_len ) -{ - - if(bx_iodebug_s.enabled) return(0x8A00); - return(0); -} - - - - - - - - - - -void bx_iodebug_c::write_handler(void *this_ptr, Bit32u addr, Bit32u dvalue, unsigned io_len) -{ - bx_iodebug_c *class_ptr = (bx_iodebug_c *) this_ptr; - class_ptr->write( addr, dvalue, io_len ); -} - - - - - - -void bx_iodebug_c::write( Bit32u addr, Bit32u dvalue, unsigned int io_len ) -{ - - -// fprintf(stderr, "IODEBUG addr: %4x\tdvalue: %8x\tio_len: %8x\n", (unsigned int)addr, (unsigned int)dvalue, io_len); - - if( addr == 0x8A01 && io_len == 2 ) - { - bx_iodebug_s.registers[bx_iodebug_s.register_select] = - (bx_iodebug_s.registers[bx_iodebug_s.register_select] << 16) + - (dvalue & 0x0000FFFF ); - } - - if( (addr != 0x8A00) || (io_len != 2) ) return; - - if( !bx_iodebug_s.enabled ) - { - if( dvalue == 0x8A00 ) - { - bx_iodebug_s.enabled = 1; -// fprintf(stderr, "IODEBUG enabled\n"); - bx_iodebug_s.registers[0] = 0; - bx_iodebug_s.registers[1] = 0; - } - return; - } - - switch( dvalue ) - { - case( 0x8A01 ): - bx_iodebug_s.register_select = 0; -// fprintf( stderr, "IODEBUG register 0 selected\n"); - break; - - case( 0x8A02 ): - bx_iodebug_s.register_select = 1; -// fprintf( stderr, "IODEBUG register 1 selected\n"); - break; - - case( 0x8A80 ): - bx_iodebug_s.register_select = 0; - bx_iodebug_c::add_range( - bx_iodebug_s.registers[0], - bx_iodebug_s.registers[1]); - bx_iodebug_s.registers[0] = 0; - bx_iodebug_s.registers[1] = 0; - break; - -#if BX_DEBUGGER - case( 0x8AE0 ): - fprintf( stderr, "request return to dbg prompt received, 0x8AE0 command (iodebug)\n"); - bx_guard.interrupt_requested=1; - break; - - case( 0x8AE2): - fprintf( stderr, "request made by the guest os to disable tracing, iodebug port 0x8A00->0x8AE2\n"); - BX_CPU(dbg_cpu)->trace = 0; - break; - - case( 0x8AE3 ): - fprintf( stderr, "request made by the guest os to enable tracing, iodebug port 0x8A00->0x8AE3\n"); - BX_CPU(dbg_cpu)->trace = 1; - break; - - case( 0x8AE4 ): - fprintf( stderr, "request made by the guest os to disable register tracing, iodebug port 0x8A00->0x8AE4\n"); - BX_CPU(dbg_cpu)->trace_reg = 0; - break; - - case( 0x8AE5 ): - fprintf( stderr, "request made by the guest os to enable register tracing, iodebug port 0x8A00->0x8AE5\n"); - BX_CPU(dbg_cpu)->trace_reg = 1; - break; - -#endif - - case( 0x8AFF ): - bx_iodebug_s.enabled = 0; -// fprintf( stderr, "IODEBUG device deactivated\n"); -// break; - -// default: -// fprintf(stderr,"IODEBUG unsupported register code\n"); - } -} - - - - - - - - -// Static function -void bx_iodebug_c::mem_write( BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data) -{ - Bit32u data32; - Bit16u data16; - Bit8u data8; - - unsigned int area; - if( !bx_iodebug_s.enabled ) return; - - area = bx_iodebug_c::range_test( addr, len ); - // Device is enabled, testing address ranges - if( area ) - { - area--; -#if BX_DEBUGGER - fprintf( stdout, "%s @ eip: %08X wrote at monitored memory location %8X\n", cpu->name, cpu->get_EIP(), addr); - bx_guard.interrupt_requested=1; -#else - fprintf( stderr, - "IODEBUG write to monitored memory area: %2i\tby EIP:\t\t%08X\n\trange start: \t\t%08X\trange end:\t%08X\n\taddress accessed:\t%08X\tdata written:\t", - area, - cpu->get_EIP(), - bx_iodebug_s.monitored_mem_areas_start[area], - bx_iodebug_s.monitored_mem_areas_end[area], - (unsigned int)addr); - - data32 = * (Bit32u *)data; - data16 = (Bit16u)data32; - data8 = (Bit8u)data32; - - switch(len) - { - case(1): - fprintf(stderr,"%02X\n", (unsigned int)data8); - break; - - case(2): - fprintf(stderr,"%04X\n", (unsigned int)data16); - break; - - case(4): - fprintf(stderr,"%08X\n", (unsigned int)data32); - break; - - default: - fprintf(stderr, "unsupported write size\n"); - } -#endif - } -} - - - - - - - - -void bx_iodebug_c::mem_read( BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data) -{ - Bit32u data32; - Bit16u data16; - Bit8u data8; - - unsigned int area; - if( !bx_iodebug_s.enabled ) return; - - area = bx_iodebug_c::range_test( addr, len ); - // Device is enabled, testing address ranges - if( area ) - { - area--; -#if BX_DEBUGGER - fprintf( stdout, "%s @ eip: %8X wrote at monitored memory location %8X\n", cpu->name, cpu->get_EIP(), addr); - bx_guard.interrupt_requested=1; -#else - fprintf( stderr, - "IODEBUG read to monitored memory area: %2i\tby EIP:\t\t%08X\n\trange start: \t\t%08X\trange end:\t%08X\n\taddress accessed:\t%08X\tdata written:\t", - area, - cpu->get_EIP(), - bx_iodebug_s.monitored_mem_areas_start[area], - bx_iodebug_s.monitored_mem_areas_end[area], - (unsigned int)addr); - data32 = * (Bit32u *)data; - data16 = (Bit16u)data32; - data8 = (Bit8u)data32; - - switch(len) - { - case(1): - fprintf(stderr,"%02X\n", (unsigned int)data8); - break; - - case(2): - fprintf(stderr,"%04X\n", (unsigned int)data16); - break; - - case(4): - fprintf(stderr,"%08X\n", (unsigned int)data32); - break; - - default: - fprintf(stderr, "unsupported write size\n"); - } -#endif - } -} - - - - - - - -unsigned int bx_iodebug_c::range_test( Bit32u addr, unsigned int len ) -{ - unsigned int i; - - for(i=0;i - -#define BX_IODEBUG_MAX_AREAS 30 - -class bx_iodebug_c : public bx_devmodel_c -{ -public: - bx_iodebug_c( void ); - ~bx_iodebug_c( void ); - virtual void init(void); - virtual void reset (unsigned type); - static void mem_write( BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data); - static void mem_read( BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data); - -private: - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); - Bit32u read(Bit32u addr, unsigned int io_len); - void write(Bit32u addr, Bit32u dvalue, unsigned int io_len); - static unsigned int range_test(Bit32u addr, unsigned int len); - static void add_range( Bit32u addr_start, Bit32u addr_end); - -}; - -extern bx_iodebug_c bx_iodebug; -#endif diff --git a/tools/ioemu/iodev/iodev.h b/tools/ioemu/iodev/iodev.h deleted file mode 100644 index 3057f6c334..0000000000 --- a/tools/ioemu/iodev/iodev.h +++ /dev/null @@ -1,422 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: iodev.h,v 1.37 2003/08/04 16:03:09 akrisak Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - -/* maximum number of emulated devices allowed. floppy, vga, etc... - you can increase this to anything below 256 since an 8-bit handle - is used for each device */ -#define BX_MAX_IO_DEVICES 30 - -/* the last device in the array is the "default" I/O device */ -#define BX_DEFAULT_IO_DEVICE (BX_MAX_IO_DEVICES-1) - -/* number of IRQ lines supported. In an ISA PC there are two - PIC chips cascaded together. each has 8 IRQ lines, so there - should be 16 IRQ's total */ -#define BX_MAX_IRQS 16 -#define BX_NO_IRQ -1 - - -class bx_pit_c; -class bx_keyb_c; -class bx_ioapic_c; -class bx_g2h_c; -#if BX_IODEBUG_SUPPORT -class bx_iodebug_c; -#endif - - - -typedef Bit32u (*bx_read_handler_t)(void *, Bit32u, unsigned); -typedef void (*bx_write_handler_t)(void *, Bit32u, Bit32u, unsigned); - - -#if BX_USE_DEV_SMF -# define BX_DEV_SMF static -# define BX_DEV_THIS bx_devices. -#else -# define BX_DEV_SMF -# define BX_DEV_THIS this-> -#endif - -////////////////////////////////////////////////////////////////////// -// bx_devmodel_c declaration -////////////////////////////////////////////////////////////////////// - -// This class defines virtual methods that are common to all devices. -// Child classes do not need to implement all of them, because in this -// definition they are defined as empty, as opposed to being pure -// virtual (= 0). -class BOCHSAPI bx_devmodel_c : public logfunctions { - public: - virtual ~bx_devmodel_c () {} - virtual void init_mem(BX_MEM_C *) {} - virtual void init(void) {} - virtual void reset(unsigned type) {} - virtual void device_load_state () {} - virtual void device_save_state () {} -}; - -////////////////////////////////////////////////////////////////////// -// declare stubs for devices -////////////////////////////////////////////////////////////////////// - -#define STUBFUNC(dev,method) \ - pluginlog->panic("%s called in %s stub. you must not have loaded the %s plugin", #dev, #method, #dev ) - -class BOCHSAPI bx_keyb_stub_c : public bx_devmodel_c { - public: - virtual ~bx_keyb_stub_c () {} - // stubs for bx_keyb_c methods - virtual void mouse_motion(int delta_x, int delta_y, unsigned button_state) { - STUBFUNC(keyboard, mouse_motion); - } - virtual void gen_scancode(Bit32u key) { - STUBFUNC(keyboard, gen_scancode); - } - virtual void paste_bytes(Bit8u *data, Bit32s length) { - STUBFUNC(keyboard, paste_bytes); - } - virtual void paste_delay_changed () { - STUBFUNC(keyboard, paste_delay_changed); - } - virtual void mouse_enabled_changed(bool enabled) { - STUBFUNC(keyboard, mouse_enabled_changed); - } -}; - -class BOCHSAPI bx_hard_drive_stub_c : public bx_devmodel_c { - public: - virtual void close_harddrive(void) { - STUBFUNC(HD, close_harddrive); - } - virtual void init() { - STUBFUNC(HD, init); - } - virtual void reset(unsigned type) { - STUBFUNC(HD, reset); - } - virtual Bit32u get_device_handle(Bit8u channel, Bit8u device) { - STUBFUNC(HD, get_device_handle); return 0; - } - virtual Bit32u get_first_cd_handle(void) { - STUBFUNC(HD, get_first_cd_handle); return 0; - } - virtual unsigned get_cd_media_status(Bit32u handle) { - STUBFUNC(HD, get_cd_media_status); return 0; - } - virtual unsigned set_cd_media_status(Bit32u handle, unsigned status) { - STUBFUNC(HD, set_cd_media_status); return 0; - } - virtual Bit32u virt_read_handler(Bit32u address, unsigned io_len) - { - STUBFUNC(HD, virt_read_handler); return 0; - } - virtual void virt_write_handler(Bit32u address, - Bit32u value, unsigned io_len) - { - STUBFUNC(HD, virt_write_handler); - } -}; - -class BOCHSAPI bx_floppy_stub_c : public bx_devmodel_c { - public: - virtual unsigned get_media_status(unsigned drive) { - STUBFUNC(floppy, get_media_status); return 0; - } - virtual unsigned set_media_status(unsigned drive, unsigned status) { - STUBFUNC(floppy, set_media_status); return 0; - } -}; - -class BOCHSAPI bx_cmos_stub_c : public bx_devmodel_c { - public: - virtual Bit32u get_reg(unsigned reg) { - STUBFUNC(cmos, get_reg); return 0; - } - virtual void set_reg(unsigned reg, Bit32u val) { - STUBFUNC(cmos, set_reg); - } - virtual time_t get_timeval() { - // STUBFUNC(cmos, get_timeval); - return 0; - } - virtual void checksum_cmos(void) { - STUBFUNC(cmos, checksum); - } -}; - -class BOCHSAPI bx_dma_stub_c : public bx_devmodel_c { - public: - virtual unsigned registerDMA8Channel( - unsigned channel, - void (* dmaRead)(Bit8u *data_byte), - void (* dmaWrite)(Bit8u *data_byte), - const char *name - ) { - STUBFUNC(dma, registerDMA8Channel); return 0; - } - virtual unsigned registerDMA16Channel( - unsigned channel, - void (* dmaRead)(Bit16u *data_word), - void (* dmaWrite)(Bit16u *data_word), - const char *name - ) { - STUBFUNC(dma, registerDMA16Channel); return 0; - } - virtual unsigned unregisterDMAChannel(unsigned channel) { - STUBFUNC(dma, unregisterDMAChannel); return 0; - } - virtual unsigned get_TC(void) { - STUBFUNC(dma, get_TC); return 0; - } - virtual void set_DRQ(unsigned channel, bx_bool val) { - STUBFUNC(dma, set_DRQ); - } - virtual void raise_HLDA(void) { - STUBFUNC(dma, raise_HLDA); - } -}; - -class BOCHSAPI bx_pic_stub_c : public bx_devmodel_c { - public: - virtual void raise_irq(unsigned irq_no) { - STUBFUNC(pic, raise_irq); - } - virtual void lower_irq(unsigned irq_no) { - STUBFUNC(pic, lower_irq); - } - virtual Bit8u IAC(void) { - STUBFUNC(pic, IAC); return 0; - } - virtual void show_pic_state(void) { - STUBFUNC(pic, show_pic_state); - } -}; - -class BOCHSAPI bx_vga_stub_c : public bx_devmodel_c { - public: - virtual void redraw_area(unsigned x0, unsigned y0, - unsigned width, unsigned height) { - STUBFUNC(vga, redraw_area); - } - virtual Bit8u mem_read(Bit32u addr) { - STUBFUNC(vga, mem_read); return 0; - } - virtual void mem_write(Bit32u addr, Bit8u value) { - STUBFUNC(vga, mem_write); - } - virtual void get_text_snapshot(Bit8u **text_snapshot, - unsigned *txHeight, unsigned *txWidth) { - STUBFUNC(vga, get_text_snapshot); - } - virtual void trigger_timer(void *this_ptr) { - STUBFUNC(vga, trigger_timer); - } - virtual void set_update_interval (unsigned interval) { - STUBFUNC(vga, set_update_interval); - } - virtual Bit8u get_actl_palette_idx(Bit8u index) { - return 0; - } -}; - -class BOCHSAPI bx_pci_stub_c : public bx_devmodel_c { - public: - virtual bx_bool register_pci_handlers(void *this_ptr, - Bit32u (*bx_pci_read_handler)(void *, Bit8u, unsigned), - void(*bx_pci_write_handler)(void *, Bit8u, Bit32u, unsigned), - Bit8u devfunc, const char *name) { - STUBFUNC(pci, register_pci_handlers); return 0; - } - virtual Bit8u rd_memType (Bit32u addr) { - return 0; - } - virtual Bit8u wr_memType (Bit32u addr) { - return 0; - } - virtual void print_i440fx_state(void) {} -}; - -class BOCHSAPI bx_ne2k_stub_c : public bx_devmodel_c { - public: - virtual void print_info(FILE *file, int page, int reg, int nodups) {} -}; - -class BOCHSAPI bx_devices_c : public logfunctions { -public: - bx_devices_c(void); - ~bx_devices_c(void); - // Register I/O addresses and IRQ lines. Initialize any internal - // structures. init() is called only once, even if the simulator - // reboots or is restarted. - void init(BX_MEM_C *); - // Enter reset state in response to a reset condition. - // The types of reset conditions are defined in bochs.h: - // power-on, hardware, or software. - void reset(unsigned type); - BX_MEM_C *mem; // address space associated with these devices - bx_bool register_io_read_handler(void *this_ptr, bx_read_handler_t f, Bit32u addr, const char *name, Bit8u mask ); - bx_bool register_io_write_handler(void *this_ptr, bx_write_handler_t f, Bit32u addr, const char *name, Bit8u mask ); - bx_bool register_default_io_read_handler(void *this_ptr, bx_read_handler_t f, const char *name, Bit8u mask ); - bx_bool register_default_io_write_handler(void *this_ptr, bx_write_handler_t f, const char *name, Bit8u mask ); - bx_bool register_irq(unsigned irq, const char *name); - bx_bool unregister_irq(unsigned irq, const char *name); - void iodev_init(void); - Bit32u inp(Bit16u addr, unsigned io_len) BX_CPP_AttrRegparmN(2); - void outp(Bit16u addr, Bit32u value, unsigned io_len) BX_CPP_AttrRegparmN(3); - - static void timer_handler(void *); - void timer(void); - - bx_devmodel_c *pluginBiosDevice; - bx_ioapic_c *ioapic; - bx_pci_stub_c *pluginPciBridge; - bx_devmodel_c *pluginPci2IsaBridge; - bx_devmodel_c *pluginPciVgaAdapter; - bx_devmodel_c *pluginPciUSBAdapter; - bx_pit_c *pit; - bx_keyb_stub_c *pluginKeyboard; - bx_dma_stub_c *pluginDmaDevice; - bx_floppy_stub_c *pluginFloppyDevice; - bx_cmos_stub_c *pluginCmosDevice; - bx_devmodel_c *pluginSerialDevice; - bx_devmodel_c *pluginParallelDevice; - bx_devmodel_c *pluginUnmapped; - bx_vga_stub_c *pluginVgaDevice; - bx_pic_stub_c *pluginPicDevice; - bx_hard_drive_stub_c *pluginHardDrive; - bx_devmodel_c *pluginSB16Device; - bx_ne2k_stub_c *pluginNE2kDevice; - bx_g2h_c *g2h; - bx_devmodel_c *pluginExtFpuIrq; - bx_devmodel_c *pluginGameport; -#if BX_IODEBUG_SUPPORT - bx_iodebug_c *iodebug; -#endif - - // stub classes that the pointers (above) can point to until a plugin is - // loaded - bx_cmos_stub_c stubCmos; - bx_keyb_stub_c stubKeyboard; - bx_hard_drive_stub_c stubHardDrive; - bx_dma_stub_c stubDma; - bx_pic_stub_c stubPic; - bx_floppy_stub_c stubFloppy; - bx_vga_stub_c stubVga; - bx_pci_stub_c stubPci; - bx_ne2k_stub_c stubNE2k; - - // Some info to pass to devices which can handled bulk IO. This allows - // the interface to remain the same for IO devices which can't handle - // bulk IO. We should probably implement special INPBulk() and OUTBulk() - // functions which stick these values in the bx_devices_c class, and - // then call the normal functions rather than having gross globals - // variables. - Bit32u bulkIOHostAddr; - unsigned bulkIOQuantumsRequested; - unsigned bulkIOQuantumsTransferred; - -private: - - Bit8u read_handler_id[0x10000]; // 64K - struct { - bx_read_handler_t funct; - void *this_ptr; - const char *handler_name; // name of device - Bit8u mask; // io_len mask - } io_read_handler[BX_MAX_IO_DEVICES]; - unsigned num_read_handles; - - Bit8u write_handler_id[0x10000]; // 64K - struct { - bx_write_handler_t funct; - void *this_ptr; - const char *handler_name; // name of device - Bit8u mask; // io_len mask - } io_write_handler[BX_MAX_IO_DEVICES]; - unsigned num_write_handles; - - // more for informative purposes, the names of the devices which - // are use each of the IRQ 0..15 lines are stored here - const char *irq_handler_name[BX_MAX_IRQS]; - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); - BX_DEV_SMF Bit32u port92_read(Bit32u address, unsigned io_len); - BX_DEV_SMF void port92_write(Bit32u address, Bit32u value, unsigned io_len); - - static Bit32u default_read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void default_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); - - int timer_handle; - bx_bool is_serial_enabled (); - bx_bool is_usb_enabled (); - bx_bool is_parallel_enabled (); - }; - - - -#if BX_PCI_SUPPORT -#include "iodev/pci.h" -#include "iodev/pci2isa.h" -#if BX_PCI_VGA_SUPPORT -#include "iodev/pcivga.h" -#endif -#if BX_PCI_USB_SUPPORT -#include "iodev/pciusb.h" -#endif -#endif -#include "iodev/vga.h" -#if BX_SUPPORT_APIC -# include "iodev/ioapic.h" -#endif -#include "iodev/biosdev.h" -#include "iodev/cmos.h" -#include "iodev/dma.h" -#include "iodev/floppy.h" -#include "iodev/harddrv.h" -#if BX_IODEBUG_SUPPORT -# include "iodev/iodebug.h" -#endif -#include "iodev/keyboard.h" -#include "iodev/parallel.h" -#include "iodev/pic.h" -#include "iodev/pit.h" -#include "iodev/pit_wrap.h" -#include "iodev/virt_timer.h" -#include "iodev/serial.h" -#if BX_SUPPORT_SB16 -# include "iodev/sb16.h" -#endif -#include "iodev/unmapped.h" -#include "iodev/eth.h" -#include "iodev/ne2k.h" -#include "iodev/guest2host.h" -#include "iodev/slowdown_timer.h" -#include "iodev/extfpuirq.h" -#include "iodev/gameport.h" diff --git a/tools/ioemu/iodev/keyboard.cc b/tools/ioemu/iodev/keyboard.cc deleted file mode 100644 index 693f4a4c60..0000000000 --- a/tools/ioemu/iodev/keyboard.cc +++ /dev/null @@ -1,1611 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: keyboard.cc,v 1.82 2003/11/11 18:18:36 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -// Now features proper implementation of keyboard opcodes 0xF4 to 0xF6 -// Silently ignores PS/2 keyboard extensions (0xF7 to 0xFD) -// Explicit panic on resend (0xFE) -// -// Emmanuel Marty - -// NB: now the PS/2 mouse support is in, outb changes meaning -// in conjunction with auxb -// auxb == 0 && outb == 0 => both buffers empty (nothing to read) -// auxb == 0 && outb == 1 => keyboard controller output buffer full -// auxb == 1 && outb == 0 => not used -// auxb == 1 && outb == 1 => mouse output buffer full. -// (das) - -// Notes from Christophe Bothamy -// -// This file includes code from Ludovic Lange (http://ludovic.lange.free.fr) -// Implementation of 3 scancodes sets mf1,mf2,mf3 with or without translation. -// Default is mf2 with translation -// Ability to switch between scancodes sets -// Ability to turn translation on or off - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#include -#include "scancodes.h" - -#define LOG_THIS theKeyboard-> -#define VERBOSE_KBD_DEBUG 0 - - -bx_keyb_c *theKeyboard = NULL; - - int -libkeyboard_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - // Create one instance of the keyboard device object. - theKeyboard = new bx_keyb_c (); - // Before this plugin was loaded, pluginKeyboard pointed to a stub. - // Now make it point to the real thing. - bx_devices.pluginKeyboard = theKeyboard; - // Register this device. - BX_REGISTER_DEVICE_DEVMODEL (plugin, type, theKeyboard, BX_PLUGIN_KEYBOARD); - return(0); // Success -} - - void -libkeyboard_LTX_plugin_fini(void) -{ - BX_INFO (("keyboard plugin_fini")); -} - -bx_keyb_c::bx_keyb_c(void) -{ - // constructor - put("KBD"); - settype(KBDLOG); -} - -bx_keyb_c::~bx_keyb_c(void) -{ - // destructor - BX_DEBUG(("Exit.")); -} - - -// flush internal buffer and reset keyboard settings to power-up condition - void -bx_keyb_c::resetinternals(bx_bool powerup) -{ - Bit32u i; - - BX_KEY_THIS s.kbd_internal_buffer.num_elements = 0; - for (i=0; iget(), 1, 1, - "8042 Keyboard controller"); - - resetinternals(1); - - BX_KEY_THIS s.kbd_internal_buffer.led_status = 0; - BX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 1; - - BX_KEY_THIS s.mouse_internal_buffer.num_elements = 0; - for (i=0; iget ())); - BX_KEY_THIS s.kbd_controller.timer_pending = 0; - - // Mouse initialization stuff - BX_KEY_THIS s.mouse.sample_rate = 100; // reports per second - BX_KEY_THIS s.mouse.resolution_cpmm = 4; // 4 counts per millimeter - BX_KEY_THIS s.mouse.scaling = 1; /* 1:1 (default) */ - BX_KEY_THIS s.mouse.mode = MOUSE_MODE_RESET; - BX_KEY_THIS s.mouse.enable = 0; - BX_KEY_THIS s.mouse.delayed_dx = 0; - BX_KEY_THIS s.mouse.delayed_dy = 0; - - for (i=0; iadd (new bx_shadow_bool_c (BXP_KBD_IRQ1_REQ, - "Keyboard IRQ1 requested: ", "", - &BX_KEY_THIS s.kbd_controller.irq1_requested)); - list->add (new bx_shadow_bool_c (BXP_KBD_IRQ12_REQ, - "Keyboard IRQ12 requested: ", "", - &BX_KEY_THIS s.kbd_controller.irq12_requested)); - list->add (new bx_shadow_num_c (BXP_KBD_TIMER_PENDING, - "Keyboard timer pending: ", "", - &BX_KEY_THIS s.kbd_controller.timer_pending)); - list->add (new bx_shadow_bool_c (BXP_KBD_PARE, - "Keyboard PARE", "", - &BX_KEY_THIS s.kbd_controller.pare)); - list->add (new bx_shadow_bool_c (BXP_KBD_TIM, - "Keyboard TIM", "", - &BX_KEY_THIS s.kbd_controller.tim)); - list->add (new bx_shadow_bool_c (BXP_KBD_AUXB, - "Keyboard AUXB", "", - &BX_KEY_THIS s.kbd_controller.auxb)); - list->add (new bx_shadow_bool_c (BXP_KBD_KEYL, - "Keyboard KEYL", "", - &BX_KEY_THIS s.kbd_controller.keyl)); - list->add (new bx_shadow_bool_c (BXP_KBD_C_D, - "Keyboard C_D", "", - &BX_KEY_THIS s.kbd_controller.c_d)); - list->add (new bx_shadow_bool_c (BXP_KBD_SYSF, - "Keyboard SYSF", "", - &BX_KEY_THIS s.kbd_controller.sysf)); - list->add (new bx_shadow_bool_c (BXP_KBD_INPB, - "Keyboard INPB", "", - &BX_KEY_THIS s.kbd_controller.inpb)); - list->add (new bx_shadow_bool_c (BXP_KBD_OUTB, - "Keyboard OUTB", "", - &BX_KEY_THIS s.kbd_controller.outb)); - } -#endif -} - - void -bx_keyb_c::reset(unsigned type) -{ - if (BX_KEY_THIS pastebuf != NULL) { - BX_KEY_THIS stop_paste = 1; - } -} - - void -bx_keyb_c::paste_delay_changed() -{ - BX_KEY_THIS pastedelay = bx_options.Okeyboard_paste_delay->get()/BX_IODEV_HANDLER_PERIOD; - BX_INFO(("will paste characters every %d keyboard ticks",BX_KEY_THIS pastedelay)); -} - - // static IO port read callback handler - // redirects to non-static class handler to avoid virtual functions - -// read function - the big picture: -// if address == data port then -// if byte for mouse then return it -// else if byte for keyboard then return it -// else address== status port -// assemble the status bits and return them. -// - Bit32u -bx_keyb_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_KEY_SMF - bx_keyb_c *class_ptr = (bx_keyb_c *) this_ptr; - - return( class_ptr->read(address, io_len) ); -} - - - Bit32u -bx_keyb_c::read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_KEY_SMF - -//BX_DEBUG(( "read from port 0x%04x", (unsigned) address)); - - if (address == 0x60) { /* output buffer */ - Bit8u val; - if (BX_KEY_THIS s.kbd_controller.auxb) { /* mouse byte available */ - val = BX_KEY_THIS s.kbd_controller.aux_output_buffer; - BX_KEY_THIS s.kbd_controller.aux_output_buffer = 0; - // BX_INFO(("kbd: %04d outb 0 auxb 0",__LINE__)); // das - BX_KEY_THIS s.kbd_controller.outb = 0; - BX_KEY_THIS s.kbd_controller.auxb = 0; - BX_KEY_THIS s.kbd_controller.irq12_requested = 0; - - if (BX_KEY_THIS s.controller_Qsize) { - unsigned i; - BX_KEY_THIS s.kbd_controller.aux_output_buffer = BX_KEY_THIS s.controller_Q[0]; - // BX_INFO(("kbd: %04d outb 1 auxb 1",__LINE__)); // das - BX_KEY_THIS s.kbd_controller.outb = 1; - BX_KEY_THIS s.kbd_controller.auxb = 1; - if (BX_KEY_THIS s.kbd_controller.allow_irq12) - BX_KEY_THIS s.kbd_controller.irq12_requested = 1; - for (i=0; i= 2 - else if (address == 0x64) { /* status register */ - - return (BX_KEY_THIS s.kbd_controller.pare << 7) | - (BX_KEY_THIS s.kbd_controller.tim << 6) | - (BX_KEY_THIS s.kbd_controller.auxb << 5) | - (BX_KEY_THIS s.kbd_controller.keyl << 4) | - (BX_KEY_THIS s.kbd_controller.c_d << 3) | - (BX_KEY_THIS s.kbd_controller.sysf << 2) | - (BX_KEY_THIS s.kbd_controller.inpb << 1) | - BX_KEY_THIS s.kbd_controller.outb; - } - -#else /* BX_CPU_LEVEL > 0 */ - /* XT MODE, System 8255 Mode Register */ - else if (address == 0x64) { /* status register */ - BX_DEBUG(("IO read from port 64h, system 8255 mode register")); - return BX_KEY_THIS s.kbd_controller.outb; - } -#endif /* BX_CPU_LEVEL > 0 */ - - BX_PANIC(("unknown address in io read to keyboard port %x", - (unsigned) address)); - return 0; /* keep compiler happy */ -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_keyb_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_KEY_SMF - bx_keyb_c *class_ptr = (bx_keyb_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - - void -bx_keyb_c::write( Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_KEY_SMF - Bit8u command_byte; - static int kbd_initialized=0; - - BX_DEBUG(("keyboard: 8-bit write to %04x = %02x", (unsigned)address, (unsigned)value)); - - switch (address) { - case 0x60: // input buffer - // if expecting data byte from command last sent to port 64h - if (BX_KEY_THIS s.kbd_controller.expecting_port60h) { - BX_KEY_THIS s.kbd_controller.expecting_port60h = 0; - // data byte written last to 0x60 - BX_KEY_THIS s.kbd_controller.c_d = 0; - if (BX_KEY_THIS s.kbd_controller.inpb) { - BX_PANIC(("write to port 60h, not ready for write")); - } - switch (BX_KEY_THIS s.kbd_controller.last_comm) { - case 0x60: // write command byte - { - bx_bool scan_convert, disable_keyboard, - disable_aux; - - scan_convert = (value >> 6) & 0x01; - disable_aux = (value >> 5) & 0x01; - disable_keyboard = (value >> 4) & 0x01; - BX_KEY_THIS s.kbd_controller.sysf = (value >> 2) & 0x01; - BX_KEY_THIS s.kbd_controller.allow_irq1 = (value >> 0) & 0x01; - BX_KEY_THIS s.kbd_controller.allow_irq12 = (value >> 1) & 0x01; - set_kbd_clock_enable(!disable_keyboard); - set_aux_clock_enable(!disable_aux); - if (BX_KEY_THIS s.kbd_controller.allow_irq12 && BX_KEY_THIS s.kbd_controller.auxb) - BX_KEY_THIS s.kbd_controller.irq12_requested = 1; - else if (BX_KEY_THIS s.kbd_controller.allow_irq1 && BX_KEY_THIS s.kbd_controller.outb) - BX_KEY_THIS s.kbd_controller.irq1_requested = 1; - - BX_DEBUG(( " allow_irq12 set to %u", (unsigned) - BX_KEY_THIS s.kbd_controller.allow_irq12)); - if ( !scan_convert ) - BX_ERROR(("keyboard: (mch) scan convert turned off")); - - // (mch) NT needs this - BX_KEY_THIS s.kbd_controller.scancodes_translate = scan_convert; - } - break; - case 0xd1: // write output port - BX_DEBUG(("write output port with value %02xh", - (unsigned) value)); - BX_SET_ENABLE_A20( (value & 0x02) != 0 ); - if (!(value & 0x01)) - BX_PANIC(("IO write: processor reset requested!")); - break; - case 0xd4: // Write to mouse - // I don't think this enables the AUX clock - //set_aux_clock_enable(1); // enable aux clock line - kbd_ctrl_to_mouse(value); - // ??? should I reset to previous value of aux enable? - break; - - case 0xd3: // write mouse output buffer - // Queue in mouse output buffer - controller_enQ(value, 1); - break; - - case 0xd2: - // Queue in keyboard output buffer - controller_enQ(value, 0); - break; - - default: - BX_PANIC(("=== unsupported write to port 60h(lastcomm=%02x): %02x", - (unsigned) BX_KEY_THIS s.kbd_controller.last_comm, (unsigned) value)); - } - } - else { - // data byte written last to 0x60 - BX_KEY_THIS s.kbd_controller.c_d = 0; - BX_KEY_THIS s.kbd_controller.expecting_port60h = 0; - /* pass byte to keyboard */ - /* ??? should conditionally pass to mouse device here ??? */ - if (BX_KEY_THIS s.kbd_controller.kbd_clock_enabled==0) { - BX_ERROR(("keyboard disabled & send of byte %02x to kbd", - (unsigned) value)); - } - kbd_ctrl_to_kbd(value); - } - break; - - case 0x64: // control register - // command byte written last to 0x64 - BX_KEY_THIS s.kbd_controller.c_d = 1; - BX_KEY_THIS s.kbd_controller.last_comm = value; - // most commands NOT expecting port60 write next - BX_KEY_THIS s.kbd_controller.expecting_port60h = 0; - - switch (value) { - case 0x20: // get keyboard command byte - BX_DEBUG(("get keyboard command byte")); - // controller output buffer must be empty - if (BX_KEY_THIS s.kbd_controller.outb) { - BX_ERROR(("kbd: OUTB set and command 0x%02x encountered", value)); - break; - } - command_byte = - (BX_KEY_THIS s.kbd_controller.scancodes_translate << 6) | - ((!BX_KEY_THIS s.kbd_controller.aux_clock_enabled) << 5) | - ((!BX_KEY_THIS s.kbd_controller.kbd_clock_enabled) << 4) | - (0 << 3) | - (BX_KEY_THIS s.kbd_controller.sysf << 2) | - (BX_KEY_THIS s.kbd_controller.allow_irq12 << 1) | - (BX_KEY_THIS s.kbd_controller.allow_irq1 << 0); - controller_enQ(command_byte, 0); - break; - case 0x60: // write command byte - BX_DEBUG(("write command byte")); - // following byte written to port 60h is command byte - BX_KEY_THIS s.kbd_controller.expecting_port60h = 1; - break; - - case 0xa0: - BX_DEBUG(("keyboard BIOS name not supported")); - break; - - case 0xa1: - BX_DEBUG(("keyboard BIOS version not supported")); - break; - - case 0xa7: // disable the aux device - set_aux_clock_enable(0); - BX_DEBUG(("aux device disabled")); - break; - case 0xa8: // enable the aux device - set_aux_clock_enable(1); - BX_DEBUG(("aux device enabled")); - break; - case 0xa9: // Test Mouse Port - // controller output buffer must be empty - if (BX_KEY_THIS s.kbd_controller.outb) { - BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value)); - break; - } - controller_enQ(0x00, 0); // no errors detected - break; - case 0xaa: // motherboard controller self test - BX_DEBUG(("Self Test")); - if( kbd_initialized == 0 ) - { - BX_KEY_THIS s.controller_Qsize = 0; - BX_KEY_THIS s.kbd_controller.outb = 0; - kbd_initialized++; - } - // controller output buffer must be empty - if (BX_KEY_THIS s.kbd_controller.outb) { - BX_ERROR(("kbd: OUTB set and command 0x%02x encountered", value)); - break; - } - // (mch) Why is this commented out??? Enabling - BX_KEY_THIS s.kbd_controller.sysf = 1; // self test complete - controller_enQ(0x55, 0); // controller OK - break; - case 0xab: // Interface Test - // controller output buffer must be empty - if (BX_KEY_THIS s.kbd_controller.outb) { -BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value)); - break; - } - controller_enQ(0x00, 0); - break; - case 0xad: // disable keyboard - set_kbd_clock_enable(0); - BX_DEBUG(("keyboard disabled")); - break; - case 0xae: // enable keyboard - set_kbd_clock_enable(1); - BX_DEBUG(("keyboard enabled")); - break; - case 0xc0: // read input port - // controller output buffer must be empty - if (BX_KEY_THIS s.kbd_controller.outb) { -BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value)); - break; - } - // keyboard power normal - controller_enQ(0x00, 0); - break; - case 0xd0: // read output port: next byte read from port 60h - BX_DEBUG(("io write to port 64h, command d0h (partial)")); - // controller output buffer must be empty - if (BX_KEY_THIS s.kbd_controller.outb) { -BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value)); - break; - } - controller_enQ( - (BX_KEY_THIS s.kbd_controller.auxb << 5) | - (BX_KEY_THIS s.kbd_controller.outb << 4) | - (BX_GET_ENABLE_A20() << 1) | - 0x01, 0); - break; - - case 0xd1: // write output port: next byte written to port 60h - BX_DEBUG(("write output port")); - // following byte to port 60h written to output port - BX_KEY_THIS s.kbd_controller.expecting_port60h = 1; - break; - - case 0xd3: // write mouse output buffer - //FIXME: Why was this a panic? - BX_DEBUG(("io write 0x64: command = 0xD3(write mouse outb)")); - // following byte to port 60h written to output port as mouse write. - BX_KEY_THIS s.kbd_controller.expecting_port60h = 1; - break; - - case 0xd4: // write to mouse - BX_DEBUG(("io write 0x64: command = 0xD4 (write to mouse)")); - // following byte written to port 60h - BX_KEY_THIS s.kbd_controller.expecting_port60h = 1; - break; - - case 0xd2: // write keyboard output buffer - BX_DEBUG(("io write 0x64: write keyboard output buffer")); - BX_KEY_THIS s.kbd_controller.expecting_port60h = 1; - break; - case 0xdd: // Disable A20 Address Line - BX_SET_ENABLE_A20(0); - break; - case 0xdf: // Enable A20 Address Line - BX_SET_ENABLE_A20(1); - break; - case 0xc1: // Continuous Input Port Poll, Low - case 0xc2: // Continuous Input Port Poll, High - case 0xe0: // Read Test Inputs - BX_PANIC(("io write 0x64: command = %02xh", (unsigned) value)); - break; - - case 0xfe: // System Reset, transition to real mode - BX_INFO(("system reset")); - bx_pc_system.ResetSignal( PCS_SET ); /* XXX is this right? */ - { - for (int i=0; ireset(BX_RESET_HARDWARE); - } - // Use bx_pc_system if necessary bx_cpu.reset_cpu(); - // bx_pc_system.ResetSignal( PCS_SET ); - break; - - default: - if (value==0xff || (value>=0xf0 && value<=0xfd)) { - /* useless pulse output bit commands ??? */ - BX_DEBUG(("io write to port 64h, useless command %02x", - (unsigned) value)); - return; - } - BX_PANIC(("unsupported io write to keyboard port %x, value = %x", - (unsigned) address, (unsigned) value)); - break; - } - break; - - default: BX_PANIC(("unknown address in bx_keyb_c::write()")); - } -} - -// service_paste_buf() transfers data from the paste buffer to the hardware -// keyboard buffer. It tries to transfer as many chars as possible at a -// time, but because different chars require different numbers of scancodes -// we have to be conservative. Note that this process depends on the -// keymap tables to know what chars correspond to what keys, and which -// chars require a shift or other modifier. -void -bx_keyb_c::service_paste_buf () -{ - if (!BX_KEY_THIS pastebuf) return; - BX_DEBUG (("service_paste_buf: ptr at %d out of %d", BX_KEY_THIS pastebuf_ptr, BX_KEY_THIS pastebuf_len)); - int fill_threshold = BX_KBD_ELEMENTS - 8; - while ( (BX_KEY_THIS pastebuf_ptr < BX_KEY_THIS pastebuf_len) && ! BX_KEY_THIS stop_paste) { - if (BX_KEY_THIS s.kbd_internal_buffer.num_elements >= fill_threshold) - return; - // there room in the buffer for a keypress and a key release. - // send one keypress and a key release. - Bit8u byte = BX_KEY_THIS pastebuf[BX_KEY_THIS pastebuf_ptr]; - BXKeyEntry *entry = bx_keymap.findAsciiChar (byte); - if (!entry) { - BX_ERROR (("paste character 0x%02x ignored", byte)); - } else { - BX_DEBUG (("pasting character 0x%02x. baseKey is %04x", byte, entry->baseKey)); - if (entry->modKey != BX_KEYMAP_UNKNOWN) - BX_KEY_THIS gen_scancode (entry->modKey); - BX_KEY_THIS gen_scancode (entry->baseKey); - BX_KEY_THIS gen_scancode (entry->baseKey | BX_KEY_RELEASED); - if (entry->modKey != BX_KEYMAP_UNKNOWN) - BX_KEY_THIS gen_scancode (entry->modKey | BX_KEY_RELEASED); - } - BX_KEY_THIS pastebuf_ptr++; - } - // reached end of pastebuf. free the memory it was using. - delete [] BX_KEY_THIS pastebuf; - BX_KEY_THIS pastebuf = NULL; - BX_KEY_THIS stop_paste = 0; -} - -// paste_bytes schedules an arbitrary number of ASCII characters to be -// inserted into the hardware queue as it become available. Any previous -// paste which is still in progress will be thrown out. BYTES is a pointer -// to a region of memory containing the chars to be pasted. When the paste -// is complete, the keyboard code will call delete [] bytes; -void -bx_keyb_c::paste_bytes (Bit8u *bytes, Bit32s length) -{ - BX_DEBUG (("paste_bytes: %d bytes", length)); - if (BX_KEY_THIS pastebuf) { - BX_ERROR (("previous paste was not completed! %d chars lost", - BX_KEY_THIS pastebuf_len - BX_KEY_THIS pastebuf_ptr)); - delete [] BX_KEY_THIS pastebuf; // free the old paste buffer - } - BX_KEY_THIS pastebuf = bytes; - BX_KEY_THIS pastebuf_ptr = 0; - BX_KEY_THIS pastebuf_len = length; - BX_KEY_THIS service_paste_buf (); -} - - void -bx_keyb_c::gen_scancode(Bit32u key) -{ - unsigned char *scancode; - Bit8u i; - - BX_DEBUG(( "gen_scancode(): %s %s", bx_keymap.getBXKeyName(key), (key >> 31)?"released":"pressed")); - - if (!BX_KEY_THIS s.kbd_controller.scancodes_translate) - BX_DEBUG(("keyboard: gen_scancode with scancode_translate cleared")); - - // Ignore scancode if keyboard clock is driven low - if (BX_KEY_THIS s.kbd_controller.kbd_clock_enabled==0) - return; - - // Ignore scancode if scanning is disabled - if (BX_KEY_THIS s.kbd_internal_buffer.scanning_enabled==0) - return; - - // Switch between make and break code - if (key & BX_KEY_RELEASED) - scancode=(unsigned char *)scancodes[(key&0xFF)][BX_KEY_THIS s.kbd_controller.current_scancodes_set].brek; - else - scancode=(unsigned char *)scancodes[(key&0xFF)][BX_KEY_THIS s.kbd_controller.current_scancodes_set].make; - - if (BX_KEY_THIS s.kbd_controller.scancodes_translate) { - // Translate before send - Bit8u escaped=0x00; - - for (i=0; i= BX_KBD_CONTROLLER_QSIZE) - BX_PANIC(("controller_enq(): controller_Q full!")); - BX_KEY_THIS s.controller_Q[BX_KEY_THIS s.controller_Qsize++] = data; - BX_KEY_THIS s.controller_Qsource = source; - return; - } - - // the Q is empty - if (source == 0) { // keyboard - BX_KEY_THIS s.kbd_controller.kbd_output_buffer = data; - // BX_INFO(("kbd: %04d outb 1 auxb 0",__LINE__)); // das - BX_KEY_THIS s.kbd_controller.outb = 1; - BX_KEY_THIS s.kbd_controller.auxb = 0; - BX_KEY_THIS s.kbd_controller.inpb = 0; - if (BX_KEY_THIS s.kbd_controller.allow_irq1) - BX_KEY_THIS s.kbd_controller.irq1_requested = 1; - } - else { // mouse - BX_KEY_THIS s.kbd_controller.aux_output_buffer = data; - // BX_INFO(("kbd: %04d outb 1 auxb 1",__LINE__)); // das - BX_KEY_THIS s.kbd_controller.outb = 1; - BX_KEY_THIS s.kbd_controller.auxb = 1; - BX_KEY_THIS s.kbd_controller.inpb = 0; - if (BX_KEY_THIS s.kbd_controller.allow_irq12) - BX_KEY_THIS s.kbd_controller.irq12_requested = 1; - } -} - -void -bx_keyb_c::kbd_enQ_imm(Bit8u val) -{ - int tail; - - if (BX_KEY_THIS s.kbd_internal_buffer.num_elements >= BX_KBD_ELEMENTS) { - BX_PANIC(("internal keyboard buffer full (imm)")); - return; - } - - /* enqueue scancode in multibyte internal keyboard buffer */ - tail = (BX_KEY_THIS s.kbd_internal_buffer.head + BX_KEY_THIS s.kbd_internal_buffer.num_elements) % - BX_KBD_ELEMENTS; - - BX_KEY_THIS s.kbd_controller.kbd_output_buffer = val; - // BX_INFO(("kbd: %04d outb 1",__LINE__)); // das - BX_KEY_THIS s.kbd_controller.outb = 1; - - if (BX_KEY_THIS s.kbd_controller.allow_irq1) - BX_KEY_THIS s.kbd_controller.irq1_requested = 1; -} - - - void -bx_keyb_c::kbd_enQ(Bit8u scancode) -{ - int tail; - - BX_DEBUG(("kbd_enQ(0x%02x)", (unsigned) scancode)); - - if (BX_KEY_THIS s.kbd_internal_buffer.num_elements >= BX_KBD_ELEMENTS) { - BX_INFO(("internal keyboard buffer full, ignoring scancode.(%02x)", - (unsigned) scancode)); - return; - } - - /* enqueue scancode in multibyte internal keyboard buffer */ - BX_DEBUG(("kbd_enQ: putting scancode 0x%02x in internal buffer", - (unsigned) scancode)); - tail = (BX_KEY_THIS s.kbd_internal_buffer.head + BX_KEY_THIS s.kbd_internal_buffer.num_elements) % - BX_KBD_ELEMENTS; - BX_KEY_THIS s.kbd_internal_buffer.buffer[tail] = scancode; - BX_KEY_THIS s.kbd_internal_buffer.num_elements++; - - if (!BX_KEY_THIS s.kbd_controller.outb && BX_KEY_THIS s.kbd_controller.kbd_clock_enabled) { - activate_timer(); - BX_DEBUG(("activating timer...")); - return; - } -//BX_DEBUG(( "# not activating timer..."); -//BX_DEBUG(( "# allow_irq1 = %u", (unsigned) BX_KEY_THIS s.kbd_controller.allow_irq1); -//BX_DEBUG(( "# outb = %u", (unsigned) BX_KEY_THIS s.kbd_controller.outb); -//BX_DEBUG(( "# clock_enab = %u", (unsigned) BX_KEY_THIS s.kbd_controller.kbd_clock_enabled); -//BX_DEBUG(( "# out_buffer = %u", (unsigned) BX_KEY_THIS s.kbd_controller.kbd_output_buffer); -} - - bx_bool BX_CPP_AttrRegparmN(3) -bx_keyb_c::mouse_enQ_packet(Bit8u b1, Bit8u b2, Bit8u b3) -{ - if ((BX_KEY_THIS s.mouse_internal_buffer.num_elements + 3) >= BX_MOUSE_BUFF_SIZE) { - return(0); /* buffer doesn't have the space */ - } - -//BX_DEBUG(("mouse: enQ_packet(%02x, %02x, %02x)", -// (unsigned) b1, (unsigned) b2, (unsigned) b3)); - - mouse_enQ(b1); - mouse_enQ(b2); - mouse_enQ(b3); - return(1); -} - - - void -bx_keyb_c::mouse_enQ(Bit8u mouse_data) -{ - int tail; - - BX_DEBUG(("mouse_enQ(%02x)", (unsigned) mouse_data)); - - if (BX_KEY_THIS s.mouse_internal_buffer.num_elements >= BX_MOUSE_BUFF_SIZE) { - BX_ERROR(("mouse: internal mouse buffer full, ignoring mouse data.(%02x)", - (unsigned) mouse_data)); - return; - } -//BX_DEBUG(( "# mouse_enq() aux_clock_enabled = %u", -// (unsigned) BX_KEY_THIS s.kbd_controller.aux_clock_enabled); - - /* enqueue mouse data in multibyte internal mouse buffer */ - tail = (BX_KEY_THIS s.mouse_internal_buffer.head + BX_KEY_THIS s.mouse_internal_buffer.num_elements) % - BX_MOUSE_BUFF_SIZE; - BX_KEY_THIS s.mouse_internal_buffer.buffer[tail] = mouse_data; - BX_KEY_THIS s.mouse_internal_buffer.num_elements++; - - if (!BX_KEY_THIS s.kbd_controller.outb && BX_KEY_THIS s.kbd_controller.aux_clock_enabled) { - activate_timer(); -//BX_DEBUG(( "# activating timer..."); - return; - } -//BX_DEBUG(( "# not activating timer..."); -//BX_DEBUG(( "# allow_irq12= %u", (unsigned) BX_KEY_THIS s.kbd_controller.allow_irq12); -//BX_DEBUG(( "# outb = %u", (unsigned) BX_KEY_THIS s.kbd_controller.outb); -//BX_DEBUG(( "# clock_enab = %u", (unsigned) BX_KEY_THIS s.kbd_controller.aux_clock_enabled); -//BX_DEBUG(( "# out_buffer = %u", (unsigned) BX_KEY_THIS s.kbd_controller.aux_output_buffer); -} - - void -bx_keyb_c::kbd_ctrl_to_kbd(Bit8u value) -{ - - BX_DEBUG(("controller passed byte %02xh to keyboard", value)); - - if (BX_KEY_THIS s.kbd_internal_buffer.expecting_typematic) { - BX_KEY_THIS s.kbd_internal_buffer.expecting_typematic = 0; - BX_KEY_THIS s.kbd_internal_buffer.delay = (value >> 5) & 0x03; - switch (BX_KEY_THIS s.kbd_internal_buffer.delay) { - case 0: BX_INFO(("setting delay to 250 mS (unused)")); break; - case 1: BX_INFO(("setting delay to 500 mS (unused)")); break; - case 2: BX_INFO(("setting delay to 750 mS (unused)")); break; - case 3: BX_INFO(("setting delay to 1000 mS (unused)")); break; - } - BX_KEY_THIS s.kbd_internal_buffer.repeat_rate = value & 0x1f; - double cps = 1 /((double)(8 + (value & 0x07)) * (double)exp(log((double)2) * (double)((value >> 3) & 0x03)) * 0.00417); - BX_INFO(("setting repeat rate to %.1f cps (unused)", cps)); - kbd_enQ(0xFA); // send ACK - return; - } - - if (BX_KEY_THIS s.kbd_internal_buffer.expecting_led_write) { - BX_KEY_THIS s.kbd_internal_buffer.expecting_led_write = 0; - BX_KEY_THIS s.kbd_internal_buffer.led_status = value; - BX_DEBUG(("LED status set to %02x", - (unsigned) BX_KEY_THIS s.kbd_internal_buffer.led_status)); - kbd_enQ(0xFA); // send ACK %%% - return; - } - - if (BX_KEY_THIS s.kbd_controller.expecting_scancodes_set) { - BX_KEY_THIS s.kbd_controller.expecting_scancodes_set = 0; - if( value != 0 ) { - if( value<4 ) { - BX_KEY_THIS s.kbd_controller.current_scancodes_set = (value-1); - BX_INFO(("Switched to scancode set %d\n", - (unsigned) BX_KEY_THIS s.kbd_controller.current_scancodes_set + 1)); - kbd_enQ(0xFA); - } - else { - BX_ERROR(("Received scancodes set out of range: %d\n", value )); - kbd_enQ(0xFF); // send ERROR - } - } - else { - // Send current scancodes set to port 0x60 - kbd_enQ( 1 + (BX_KEY_THIS s.kbd_controller.current_scancodes_set) ); - } - return; - } - - switch (value) { - case 0x00: // ??? ignore and let OS timeout with no response - kbd_enQ(0xFA); // send ACK %%% - return; - break; - - case 0x05: // ??? - // (mch) trying to get this to work... - BX_KEY_THIS s.kbd_controller.sysf = 1; - kbd_enQ_imm(0xfe); - return; - break; - - case 0xed: // LED Write - BX_KEY_THIS s.kbd_internal_buffer.expecting_led_write = 1; - kbd_enQ_imm(0xFA); // send ACK %%% - return; - break; - - case 0xee: // echo - kbd_enQ(0xEE); // return same byte (EEh) as echo diagnostic - return; - break; - - case 0xf0: // Select alternate scan code set - BX_KEY_THIS s.kbd_controller.expecting_scancodes_set = 1; - BX_DEBUG(("Expecting scancode set info...\n")); - kbd_enQ(0xFA); // send ACK - return; - break; - - case 0xf2: // identify keyboard - BX_INFO(("identify keyboard command received")); - - // XT sends nothing, AT sends ACK - // MFII with translation sends ACK+ABh+41h - // MFII without translation sends ACK+ABh+83h - if (bx_options.Okeyboard_type->get() != BX_KBD_XT_TYPE) { - kbd_enQ(0xFA); - if (bx_options.Okeyboard_type->get() == BX_KBD_MF_TYPE) { - kbd_enQ(0xAB); - - if(BX_KEY_THIS s.kbd_controller.scancodes_translate) - kbd_enQ(0x41); - else - kbd_enQ(0x83); - } - } - return; - break; - - case 0xf3: // typematic info - BX_KEY_THIS s.kbd_internal_buffer.expecting_typematic = 1; - BX_INFO(("setting typematic info")); - kbd_enQ(0xFA); // send ACK - return; - break; - - case 0xf4: // enable keyboard - BX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 1; - kbd_enQ(0xFA); // send ACK - return; - break; - - case 0xf5: // reset keyboard to power-up settings and disable scanning - resetinternals(1); - kbd_enQ(0xFA); // send ACK - BX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 0; - BX_INFO(("reset-disable command received")); - return; - break; - - case 0xf6: // reset keyboard to power-up settings and enable scanning - resetinternals(1); - kbd_enQ(0xFA); // send ACK - BX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 1; - BX_INFO(("reset-enable command received")); - return; - break; - - case 0xf7: // PS/2 Set All Keys To Typematic - case 0xf8: // PS/2 Set All Keys to Make/Break - case 0xf9: // PS/2 PS/2 Set All Keys to Make - case 0xfa: // PS/2 Set All Keys to Typematic Make/Break - case 0xfb: // PS/2 Set Key Type to Typematic - case 0xfc: // PS/2 Set Key Type to Make/Break - case 0xfd: // PS/2 Set Key Type to Make - // Silently ignore and let the OS timeout, for now. - // If anyone has code around that makes use of that, I can - // provide documentation on their behavior (ask core@ggi-project.org) - return; - break; - - case 0xfe: // resend. aiiee. - BX_PANIC( ("got 0xFE (resend)")); - return; - break; - - case 0xff: // reset: internal keyboard reset and afterwards the BAT - BX_DEBUG(("reset command received")); - resetinternals(1); - kbd_enQ(0xFA); // send ACK - kbd_enQ(0xAA); // BAT test passed - return; - break; - - case 0xd3: - kbd_enQ(0xfa); - return; - - default: - /* XXX fix this properly: - http://panda.cs.ndsu.nodak.edu/~achapwes/PICmicro/mouse/mouse.html - http://sourceforge.net/tracker/index.php?func=detail&aid=422457&group_id=12580&atid=112580 - */ - BX_ERROR(("kbd_ctrl_to_kbd(): got value of %02x", - (unsigned) value)); - kbd_enQ(0xFA); /* send ACK ??? */ - return; - break; - } -} - - void -bx_keyb_c::timer_handler(void *this_ptr) -{ - bx_keyb_c *class_ptr = (bx_keyb_c *) this_ptr; - unsigned retval; - - // retval=class_ptr->periodic( bx_options.Okeyboard_serial_delay->get()); - retval=class_ptr->periodic(1); - - if(retval&0x01) - DEV_pic_raise_irq(1); - if(retval&0x02) - DEV_pic_raise_irq(12); -} - - unsigned -bx_keyb_c::periodic( Bit32u usec_delta ) -{ -/* static int multiple=0; */ - static unsigned count_before_paste=0; - Bit8u retval; - - UNUSED( usec_delta ); - - if (BX_KEY_THIS s.kbd_controller.kbd_clock_enabled ) { - if(++count_before_paste>=BX_KEY_THIS pastedelay) { - // after the paste delay, consider adding moving more chars - // from the paste buffer to the keyboard buffer. - BX_KEY_THIS service_paste_buf (); - count_before_paste=0; - } - } - - retval = BX_KEY_THIS s.kbd_controller.irq1_requested | (BX_KEY_THIS s.kbd_controller.irq12_requested << 1); - BX_KEY_THIS s.kbd_controller.irq1_requested = 0; - BX_KEY_THIS s.kbd_controller.irq12_requested = 0; - - if ( BX_KEY_THIS s.kbd_controller.timer_pending == 0 ) { - return(retval); - } - - if ( usec_delta >= BX_KEY_THIS s.kbd_controller.timer_pending ) { - BX_KEY_THIS s.kbd_controller.timer_pending = 0; - } - else { - BX_KEY_THIS s.kbd_controller.timer_pending -= usec_delta; - return(retval); - } - - if (BX_KEY_THIS s.kbd_controller.outb) { - return(retval); - } - - /* nothing in outb, look for possible data xfer from keyboard or mouse */ - if (BX_KEY_THIS s.kbd_controller.kbd_clock_enabled && BX_KEY_THIS s.kbd_internal_buffer.num_elements) { -//BX_DEBUG(( "# servicing keyboard code"); - BX_DEBUG(("service_keyboard: key in internal buffer waiting")); - BX_KEY_THIS s.kbd_controller.kbd_output_buffer = - BX_KEY_THIS s.kbd_internal_buffer.buffer[BX_KEY_THIS s.kbd_internal_buffer.head]; - // BX_INFO(("kbd: %04d outb 1",__LINE__)); // das - BX_KEY_THIS s.kbd_controller.outb = 1; - // commented out since this would override the current state of the - // mouse buffer flag - no bug seen - just seems wrong (das) - // BX_KEY_THIS s.kbd_controller.auxb = 0; -//BX_DEBUG(( "# ___kbd::periodic kbd"); - BX_KEY_THIS s.kbd_internal_buffer.head = (BX_KEY_THIS s.kbd_internal_buffer.head + 1) % - BX_KBD_ELEMENTS; - BX_KEY_THIS s.kbd_internal_buffer.num_elements--; - if (BX_KEY_THIS s.kbd_controller.allow_irq1) - BX_KEY_THIS s.kbd_controller.irq1_requested = 1; - } - else { - create_mouse_packet(0); - if (BX_KEY_THIS s.kbd_controller.aux_clock_enabled && BX_KEY_THIS s.mouse_internal_buffer.num_elements) { -//BX_DEBUG(( "# servicing mouse code"); - BX_DEBUG(("service_keyboard: key(from mouse) in internal buffer waiting")); - BX_KEY_THIS s.kbd_controller.aux_output_buffer = - BX_KEY_THIS s.mouse_internal_buffer.buffer[BX_KEY_THIS s.mouse_internal_buffer.head]; - - // BX_INFO(("kbd: %04d outb 1 auxb 1",__LINE__)); //das - BX_KEY_THIS s.kbd_controller.outb = 1; - BX_KEY_THIS s.kbd_controller.auxb = 1; -//BX_DEBUG(( "# ___kbd:periodic aux"); - BX_KEY_THIS s.mouse_internal_buffer.head = (BX_KEY_THIS s.mouse_internal_buffer.head + 1) % - BX_MOUSE_BUFF_SIZE; - BX_KEY_THIS s.mouse_internal_buffer.num_elements--; -//BX_DEBUG(( "# allow12 = %u", (unsigned) BX_KEY_THIS s.kbd_controller.allow_irq12); - if (BX_KEY_THIS s.kbd_controller.allow_irq12) - BX_KEY_THIS s.kbd_controller.irq12_requested = 1; - } - else { - BX_DEBUG(("service_keyboard(): no keys waiting")); - } - } - return(retval); -} - - - - - void -bx_keyb_c::activate_timer(void) -{ - if (BX_KEY_THIS s.kbd_controller.timer_pending == 0) { - // BX_KEY_THIS s.kbd_controller.timer_pending = bx_options.Okeyboard_serial_delay->get (); - BX_KEY_THIS s.kbd_controller.timer_pending = 1; - } -} - - - void -bx_keyb_c::kbd_ctrl_to_mouse(Bit8u value) -{ -BX_DEBUG(("MOUSE: kbd_ctrl_to_mouse(%02xh)", (unsigned) value)); -BX_DEBUG((" enable = %u", (unsigned) BX_KEY_THIS s.mouse.enable)); -BX_DEBUG((" allow_irq12 = %u", - (unsigned) BX_KEY_THIS s.kbd_controller.allow_irq12)); -BX_DEBUG((" aux_clock_enabled = %u", - (unsigned) BX_KEY_THIS s.kbd_controller.aux_clock_enabled)); -//BX_DEBUG(( "MOUSE: kbd_ctrl_to_mouse(%02xh)", (unsigned) value)); - - // an ACK (0xFA) is always the first response to any valid input - // received from the system other than Set-Wrap-Mode & Resend-Command - - - if (BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter) { - BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 0; - switch (BX_KEY_THIS s.kbd_controller.last_mouse_command) { - case 0xf3: // Set Mouse Sample Rate - BX_KEY_THIS s.mouse.sample_rate = value; - BX_DEBUG(("[mouse] Sampling rate set: %d Hz", value)); - controller_enQ(0xFA, 1); // ack - break; - - case 0xe8: // Set Mouse Resolution - switch (value) { - case 0: - BX_KEY_THIS s.mouse.resolution_cpmm = 1; - break; - case 1: - BX_KEY_THIS s.mouse.resolution_cpmm = 2; - break; - case 2: - BX_KEY_THIS s.mouse.resolution_cpmm = 4; - break; - case 3: - BX_KEY_THIS s.mouse.resolution_cpmm = 8; - break; - default: - BX_PANIC(("[mouse] Unknown resolution %d", value)); - break; - } - BX_DEBUG(("[mouse] Resolution set to %d counts per mm", - BX_KEY_THIS s.mouse.resolution_cpmm)); - - controller_enQ(0xFA, 1); // ack - break; - - default: - BX_PANIC(("MOUSE: unknown last command (%02xh)", (unsigned) BX_KEY_THIS s.kbd_controller.last_mouse_command)); - } - } else { - BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 0; - BX_KEY_THIS s.kbd_controller.last_mouse_command = value; - - // test for wrap mode first - if (BX_KEY_THIS s.mouse.mode == MOUSE_MODE_WRAP) { - // if not a reset command or reset wrap mode - // then just echo the byte. - if ((value != 0xff) && (value != 0xec)) { - if (bx_dbg.mouse) - BX_INFO(("[mouse] wrap mode: Ignoring command %0X02.",value)); - controller_enQ(value,1); - // bail out - return; - } - } - switch ( value ) { - case 0xe6: // Set Mouse Scaling to 1:1 - controller_enQ(0xFA, 1); // ACK - BX_KEY_THIS s.mouse.scaling = 2; - BX_DEBUG(("[mouse] Scaling set to 1:1")); - break; - - case 0xe7: // Set Mouse Scaling to 2:1 - controller_enQ(0xFA, 1); // ACK - BX_KEY_THIS s.mouse.scaling = 2; - BX_DEBUG(("[mouse] Scaling set to 2:1")); - break; - - case 0xe8: // Set Mouse Resolution - controller_enQ(0xFA, 1); // ACK - BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 1; - break; - - case 0xea: // Set Stream Mode - if (bx_dbg.mouse) - BX_INFO(("[mouse] Mouse stream mode on.")); - BX_KEY_THIS s.mouse.mode = MOUSE_MODE_STREAM; - controller_enQ(0xFA, 1); // ACK - break; - - case 0xec: // Reset Wrap Mode - // unless we are in wrap mode ignore the command - if ( BX_KEY_THIS s.mouse.mode == MOUSE_MODE_WRAP) { - if (bx_dbg.mouse) - BX_INFO(("[mouse] Mouse wrap mode off.")); - // restore previous mode except disable stream mode reporting. - // ### TODO disabling reporting in stream mode - BX_KEY_THIS s.mouse.mode = BX_KEY_THIS s.mouse.saved_mode; - controller_enQ(0xFA, 1); // ACK - } - break; - case 0xee: // Set Wrap Mode - // ### TODO flush output queue. - // ### TODO disable interrupts if in stream mode. - if (bx_dbg.mouse) - BX_INFO(("[mouse] Mouse wrap mode on.")); - BX_KEY_THIS s.mouse.saved_mode = BX_KEY_THIS s.mouse.mode; - BX_KEY_THIS s.mouse.mode = MOUSE_MODE_WRAP; - controller_enQ(0xFA, 1); // ACK - break; - - case 0xf0: // Set Remote Mode (polling mode, i.e. not stream mode.) - if (bx_dbg.mouse) - BX_INFO(("[mouse] Mouse remote mode on.")); - // ### TODO should we flush/discard/ignore any already queued packets? - BX_KEY_THIS s.mouse.mode = MOUSE_MODE_REMOTE; - controller_enQ(0xFA, 1); // ACK - break; - - - case 0xf2: // Read Device Type - controller_enQ(0xFA, 1); // ACK - controller_enQ(0x00, 1); // Device ID - BX_DEBUG(("[mouse] Read mouse ID")); - break; - - case 0xf3: // Set Mouse Sample Rate (sample rate written to port 60h) - controller_enQ(0xFA, 1); // ACK - BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 1; - break; - - case 0xf4: // Enable (in stream mode) - BX_KEY_THIS s.mouse.enable = 1; - controller_enQ(0xFA, 1); // ACK - BX_DEBUG(("[mouse] Mouse enabled (stream mode)")); - break; - - case 0xf5: // Disable (in stream mode) - BX_KEY_THIS s.mouse.enable = 0; - controller_enQ(0xFA, 1); // ACK - BX_DEBUG(("[mouse] Mouse disabled (stream mode)")); - break; - - case 0xf6: // Set Defaults - BX_KEY_THIS s.mouse.sample_rate = 100; /* reports per second (default) */ - BX_KEY_THIS s.mouse.resolution_cpmm = 4; /* 4 counts per millimeter (default) */ - BX_KEY_THIS s.mouse.scaling = 1; /* 1:1 (default) */ - BX_KEY_THIS s.mouse.enable = 0; - BX_KEY_THIS s.mouse.mode = MOUSE_MODE_STREAM; - controller_enQ(0xFA, 1); // ACK - BX_DEBUG(("[mouse] Set Defaults")); - break; - - case 0xff: // Reset - BX_KEY_THIS s.mouse.sample_rate = 100; /* reports per second (default) */ - BX_KEY_THIS s.mouse.resolution_cpmm = 4; /* 4 counts per millimeter (default) */ - BX_KEY_THIS s.mouse.scaling = 1; /* 1:1 (default) */ - BX_KEY_THIS s.mouse.mode = MOUSE_MODE_RESET; - BX_KEY_THIS s.mouse.enable = 0; - /* (mch) NT expects an ack here */ - controller_enQ(0xFA, 1); // ACK - controller_enQ(0xAA, 1); // completion code - controller_enQ(0x00, 1); // ID code (normal mouse, wheelmouse has id 0x3) - BX_DEBUG(("[mouse] Mouse reset")); - break; - - case 0xe9: // Get mouse information - // should we ack here? (mch): Yes - controller_enQ(0xFA, 1); // ACK - controller_enQ(BX_KEY_THIS s.mouse.get_status_byte(), 1); // status - controller_enQ(BX_KEY_THIS s.mouse.get_resolution_byte(), 1); // resolution - controller_enQ(BX_KEY_THIS s.mouse.sample_rate, 1); // sample rate - BX_DEBUG(("[mouse] Get mouse information")); - break; - - case 0xeb: // Read Data (send a packet when in Remote Mode) - controller_enQ(0xFA, 1); // ACK - // perhaps we should be adding some movement here. - mouse_enQ_packet( ((BX_KEY_THIS s.mouse.button_status & 0x0f) | 0x08), - 0x00, 0x00 ); // bit3 of first byte always set - //assumed we really aren't in polling mode, a rather odd assumption. - BX_ERROR(("[mouse] Warning: Read Data command partially supported.")); - break; - - default: - //FEh Resend - BX_PANIC(("MOUSE: kbd_ctrl_to_mouse(%02xh)", (unsigned) value)); - } - } -} - -void -bx_keyb_c::create_mouse_packet(bool force_enq) { - Bit8u b1, b2, b3; - - // BX_DEBUG("Calling create_mouse_packet: force_enq=%d\n",force_enq); - - if(BX_KEY_THIS s.mouse_internal_buffer.num_elements && !force_enq) - return; - - // BX_DEBUG("Got to first milestone: force_enq=%d\n",force_enq); - - Bit16s delta_x = BX_KEY_THIS s.mouse.delayed_dx; - Bit16s delta_y = BX_KEY_THIS s.mouse.delayed_dy; - Bit8u button_state=BX_KEY_THIS s.mouse.button_status | 0x08; - - if(!force_enq && !delta_x && !delta_y) { - return; - } - - // BX_DEBUG("Got to second milestone: delta_x=%d, delta_y=%d\n",delta_x,delta_y); - - if(delta_x>254) delta_x=254; - if(delta_x<-254) delta_x=-254; - if(delta_y>254) delta_y=254; - if(delta_y<-254) delta_y=-254; - - b1 = (button_state & 0x0f) | 0x08; // bit3 always set - - if ( (delta_x>=0) && (delta_x<=255) ) { - b2 = (Bit8u) delta_x; - BX_KEY_THIS s.mouse.delayed_dx-=delta_x; - } - else if ( delta_x > 255 ) { - b2 = (Bit8u) 0xff; - BX_KEY_THIS s.mouse.delayed_dx-=255; - } - else if ( delta_x >= -256 ) { - b2 = (Bit8u) delta_x; - b1 |= 0x10; - BX_KEY_THIS s.mouse.delayed_dx-=delta_x; - } - else { - b2 = (Bit8u) 0x00; - b1 |= 0x10; - BX_KEY_THIS s.mouse.delayed_dx+=256; - } - - if ( (delta_y>=0) && (delta_y<=255) ) { - b3 = (Bit8u) delta_y; - BX_KEY_THIS s.mouse.delayed_dy-=delta_y; - } - else if ( delta_y > 255 ) { - b3 = (Bit8u) 0xff; - BX_KEY_THIS s.mouse.delayed_dy-=255; - } - else if ( delta_y >= -256 ) { - b3 = (Bit8u) delta_y; - b1 |= 0x20; - BX_KEY_THIS s.mouse.delayed_dy-=delta_y; - } - else { - b3 = (Bit8u) 0x00; - b1 |= 0x20; - BX_KEY_THIS s.mouse.delayed_dy+=256; - } - mouse_enQ_packet(b1, b2, b3); -} - - -void -bx_keyb_c::mouse_enabled_changed(bool enabled) { - if(s.mouse.delayed_dx || BX_KEY_THIS s.mouse.delayed_dy) { - create_mouse_packet(1); - } - s.mouse.delayed_dx=0; - s.mouse.delayed_dy=0; - BX_DEBUG(("Keyboard mouse disable called.")); -} - - void -bx_keyb_c::mouse_motion(int delta_x, int delta_y, unsigned button_state) -{ - bool force_enq=0; - - // If mouse events are disabled on the GUI headerbar, don't - // generate any mouse data - if (bx_options.Omouse_enabled->get () == 0) - return; - - - // don't generate interrupts if we are in remote mode. - if ( BX_KEY_THIS s.mouse.mode == MOUSE_MODE_REMOTE) - // is there any point in doing any work if we don't act on the result - // so go home. - return; - - - // Note: enable only applies in STREAM MODE. - if ( BX_KEY_THIS s.mouse.enable==0 ) - return; - - // scale down the motion - if ( (delta_x < -1) || (delta_x > 1) ) - delta_x /= 2; - if ( (delta_y < -1) || (delta_y > 1) ) - delta_y /= 2; - -#ifdef VERBOSE_KBD_DEBUG - if (delta_x != 0 || delta_y != 0) - BX_DEBUG(("[mouse] Dx=%d Dy=%d", delta_x, delta_y)); -#endif /* ifdef VERBOSE_KBD_DEBUG */ - - if( (delta_x==0) && (delta_y==0) && (BX_KEY_THIS s.mouse.button_status == (button_state & 0x3) ) ) { - BX_DEBUG(("Ignoring useless mouse_motion call:\n")); - BX_DEBUG(("This should be fixed in the gui code.\n")); - return; - } - - if(BX_KEY_THIS s.mouse.button_status != (button_state & 0x3)) { - force_enq=1; - } - - BX_KEY_THIS s.mouse.button_status = button_state & 0x3; - - if(delta_x>255) delta_x=255; - if(delta_y>255) delta_y=255; - if(delta_x<-256) delta_x=-256; - if(delta_y<-256) delta_y=-256; - - BX_KEY_THIS s.mouse.delayed_dx+=delta_x; - BX_KEY_THIS s.mouse.delayed_dy+=delta_y; - - if((BX_KEY_THIS s.mouse.delayed_dx>255)|| - (BX_KEY_THIS s.mouse.delayed_dx<-256)|| - (BX_KEY_THIS s.mouse.delayed_dy>255)|| - (BX_KEY_THIS s.mouse.delayed_dy<-256)) { - force_enq=1; - } - - create_mouse_packet(force_enq); -} - - - int -bx_keyb_c::SaveState( class state_file *fd ) -{ - fd->write_check ("keyboard start"); - fd->write (&BX_KEY_THIS s, sizeof (BX_KEY_THIS s)); - fd->write_check ("keyboard end"); - return(0); -} - - - int -bx_keyb_c::LoadState( class state_file *fd ) -{ - fd->read_check ("keyboard start"); - fd->read (&BX_KEY_THIS s, sizeof (BX_KEY_THIS s)); - fd->read_check ("keyboard end"); - return(0); -} - diff --git a/tools/ioemu/iodev/keyboard.h b/tools/ioemu/iodev/keyboard.h deleted file mode 100644 index 24d9ccfdf0..0000000000 --- a/tools/ioemu/iodev/keyboard.h +++ /dev/null @@ -1,234 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: keyboard.h,v 1.22 2003/07/13 19:51:21 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -#ifndef _PCKEY_H -#define _PCKEY_H - - -#define BX_KBD_ELEMENTS 16 -#define BX_MOUSE_BUFF_SIZE 48 - -// these keywords should only be used in keyboard.cc -#if BX_USE_KEY_SMF -# define BX_KEY_SMF static -# define BX_KEY_THIS theKeyboard-> -#else -# define BX_KEY_SMF -# define BX_KEY_THIS -#endif - -#define MOUSE_MODE_RESET 10 -#define MOUSE_MODE_STREAM 11 -#define MOUSE_MODE_REMOTE 12 -#define MOUSE_MODE_WRAP 13 - -class bx_keyb_c : public bx_keyb_stub_c { -public: - bx_keyb_c(void); - ~bx_keyb_c(void); - // implement bx_devmodel_c interface - virtual void init(void); - virtual void reset(unsigned type); - // override stubs from bx_keyb_stub_c - virtual void gen_scancode(Bit32u key); - virtual void paste_bytes(Bit8u *data, Bit32s length); - virtual void mouse_motion(int delta_x, int delta_y, unsigned button_state); - - // update the paste delay based on bx_options.Okeyboard_paste_delay - virtual void paste_delay_changed (); - virtual void mouse_enabled_changed(bool enabled); - -private: - BX_KEY_SMF Bit8u get_kbd_enable(void); - BX_KEY_SMF void service_paste_buf (); - BX_KEY_SMF void create_mouse_packet(bool force_enq); - BX_KEY_SMF void mouse_button(unsigned mouse_state); - BX_KEY_SMF int SaveState( class state_file *fd ); - BX_KEY_SMF int LoadState( class state_file *fd ); - BX_KEY_SMF unsigned periodic( Bit32u usec_delta ); - - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); -#if !BX_USE_KEY_SMF - void write(Bit32u address, Bit32u value, unsigned io_len); - Bit32u read(Bit32u address, unsigned io_len); -#endif - - struct { - struct { - /* status bits matching the status port*/ - bx_bool pare; // Bit7, 1= parity error from keyboard/mouse - ignored. - bx_bool tim; // Bit6, 1= timeout from keyboard - ignored. - bx_bool auxb; // Bit5, 1= mouse data waiting for CPU to read. - bx_bool keyl; // Bit4, 1= keyswitch in lock position - ignored. - bx_bool c_d; /* Bit3, 1=command to port 64h, 0=data to port 60h */ - bx_bool sysf; // Bit2, - bx_bool inpb; // Bit1, - bx_bool outb; // Bit0, 1= keyboard data or mouse data ready for CPU - // check aux to see which. Or just keyboard - // data before AT style machines - - /* internal to our version of the keyboard controller */ - bx_bool kbd_clock_enabled; - bx_bool aux_clock_enabled; - bx_bool allow_irq1; - bx_bool allow_irq12; - Bit8u kbd_output_buffer; - Bit8u aux_output_buffer; - Bit8u last_comm; - Bit8u expecting_port60h; - Bit8u expecting_mouse_parameter; - Bit8u last_mouse_command; - Bit32u timer_pending; - bx_bool irq1_requested; - bx_bool irq12_requested; - bx_bool scancodes_translate; - bx_bool expecting_scancodes_set; - Bit8u current_scancodes_set; - } kbd_controller; - - struct mouseStruct { - Bit8u sample_rate; - Bit8u resolution_cpmm; // resolution in counts per mm - Bit8u scaling; - Bit8u mode; - Bit8u saved_mode; // the mode prior to entering wrap mode - bx_bool enable; - - Bit8u get_status_byte () - { - // top bit is 0 , bit 6 is 1 if remote mode. - Bit8u ret = (Bit8u) ((mode == MOUSE_MODE_REMOTE) ? 0x40 : 0); - ret |= (enable << 5); - ret |= (scaling == 1) ? 0 : (1 << 4); - ret |= ((button_status & 0x1) << 2); - ret |= ((button_status & 0x2) << 0); - return ret; - } - - Bit8u get_resolution_byte () - { - Bit8u ret = 0; - - switch (resolution_cpmm) { - case 1: - ret = 0; - break; - - case 2: - ret = 1; - break; - - case 4: - ret = 2; - break; - - case 8: - ret = 3; - break; - - default: - genlog->panic("mouse: invalid resolution_cpmm"); - }; - return ret; - } - - Bit8u button_status; - Bit16s delayed_dx; - Bit16s delayed_dy; - } mouse; - - struct { - int num_elements; - Bit8u buffer[BX_KBD_ELEMENTS]; - int head; - bx_bool expecting_typematic; - bx_bool expecting_led_write; - Bit8u delay; - Bit8u repeat_rate; - Bit8u led_status; - bx_bool scanning_enabled; - } kbd_internal_buffer; - - struct { - int num_elements; - Bit8u buffer[BX_MOUSE_BUFF_SIZE]; - int head; - } mouse_internal_buffer; -#define BX_KBD_CONTROLLER_QSIZE 5 - Bit8u controller_Q[BX_KBD_CONTROLLER_QSIZE]; - unsigned controller_Qsize; - unsigned controller_Qsource; // 0=keyboard, 1=mouse - } s; // State information for saving/loading - - // The paste buffer does NOT exist in the hardware. It is a bochs - // construction that allows the user to "paste" arbitrary length sequences of - // keystrokes into the emulated machine. Since the hardware buffer is only - // 16 bytes, a very small amount of data can be added to the hardware buffer - // at a time. The paste buffer keeps track of the bytes that have not yet - // been pasted. - // - // Lifetime of a paste buffer: The paste data comes from the system - // clipboard, which must be accessed using platform independent code in the - // gui. Because every gui has its own way of managing the clipboard memory - // (in X windows, you're supposed to call Xfree for example), in the platform - // specific code we make a copy of the clipboard buffer with - // "new Bit8u[length]". Then the pointer is passed into - // bx_keyb_c::paste_bytes, along with the length. The gui code never touches - // the pastebuf again, and does not free it. The keyboard code is - // responsible for deallocating the paste buffer using delete [] buf. The - // paste buffer is binary data, and it is probably NOT null terminated. - // - // Summary: A paste buffer is allocated (new) in the platform-specific gui - // code, passed to the keyboard model, and is freed (delete[]) when it is no - // longer needed. - Bit8u *pastebuf; // ptr to bytes to be pasted, or NULL if none in progress - Bit32u pastebuf_len; // length of pastebuf - Bit32u pastebuf_ptr; // ptr to next byte to be added to hw buffer - Bit32u pastedelay; // count before paste - bx_bool stop_paste; // stop the current paste operation on hardware reset - - BX_KEY_SMF void resetinternals(bx_bool powerup); - BX_KEY_SMF void set_kbd_clock_enable(Bit8u value) BX_CPP_AttrRegparmN(1); - BX_KEY_SMF void set_aux_clock_enable(Bit8u value); - BX_KEY_SMF void kbd_ctrl_to_kbd(Bit8u value); - BX_KEY_SMF void kbd_ctrl_to_mouse(Bit8u value); - BX_KEY_SMF void kbd_enQ(Bit8u scancode); - BX_KEY_SMF void kbd_enQ_imm(Bit8u val); - BX_KEY_SMF void activate_timer(void); - BX_KEY_SMF void controller_enQ(Bit8u data, unsigned source); - BX_KEY_SMF bx_bool mouse_enQ_packet(Bit8u b1, Bit8u b2, Bit8u b3) BX_CPP_AttrRegparmN(3); - BX_KEY_SMF void mouse_enQ(Bit8u mouse_data); - - static void timer_handler(void *); - void timer(void); - int timer_handle; - }; - - -#endif // #ifndef _PCKEY_H diff --git a/tools/ioemu/iodev/load32bitOShack.cc b/tools/ioemu/iodev/load32bitOShack.cc deleted file mode 100644 index 6a0a4904d8..0000000000 --- a/tools/ioemu/iodev/load32bitOShack.cc +++ /dev/null @@ -1,322 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: load32bitOShack.cc,v 1.14 2003/08/08 00:05:53 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - - -#include "bochs.h" -#define LOG_THIS genlog-> - - - -static void bx_load_linux_hack(void); -static void bx_load_null_kernel_hack(void); -static Bit32u bx_load_kernel_image(char *path, Bit32u paddr); - - void -bx_load32bitOSimagehack(void) -{ - // Replay IO from log to initialize IO devices to - // a reasonable state needed for the OS. This is done - // in lieu of running the 16-bit BIOS to init things, - // since we want to test straight 32bit stuff for - // freemware. - -#ifndef BX_USE_VMX - FILE *fp; - - fp = fopen(bx_options.load32bitOSImage.Oiolog->getptr (), "r"); - - if (fp == NULL) { - BX_PANIC(("could not open IO init file.")); - } - - while (1) { - unsigned len, op, port, val; - int ret; - ret = fscanf(fp, "%u %u %x %x\n", - &len, &op, &port, &val); - if (ret != 4) { - BX_PANIC(("could not open IO init file.")); - } - if (op == 0) { - // read - (void) bx_devices.inp(port, len); - } - else if (op == 1) { - // write - bx_devices.outp(port, val, len); - } - else { - BX_PANIC(("bad IO op in init filen")); - } - if (feof(fp)) break; - } -#endif - - // Invoke proper hack depending on which OS image we're loading - switch (bx_options.load32bitOSImage.OwhichOS->get ()) { - case Load32bitOSLinux: - bx_load_linux_hack(); - break; - case Load32bitOSNullKernel: - bx_load_null_kernel_hack(); - break; - default: - BX_PANIC(("load32bitOSImage: OS not recognized")); - } -} - -struct gdt_entry -{ - Bit32u low; - Bit32u high; -}; -struct linux_setup_params -{ - /* 0x000 */ Bit8u orig_x; - /* 0x001 */ Bit8u orig_y; - /* 0x002 */ Bit16u memory_size_std; - /* 0x004 */ Bit16u orig_video_page; - /* 0x006 */ Bit8u orig_video_mode; - /* 0x007 */ Bit8u orig_video_cols; - /* 0x008 */ Bit16u unused1; - /* 0x00a */ Bit16u orig_video_ega_bx; - /* 0x00c */ Bit16u unused2; - /* 0x00e */ Bit8u orig_video_lines; - /* 0x00f */ Bit8u orig_video_isVGA; - /* 0x010 */ Bit16u orig_video_points; - /* 0x012 */ Bit8u pad1[0x40 - 0x12]; - /* 0x040 */ Bit8u apm_info[0x80 - 0x40]; - /* 0x080 */ Bit8u hd0_info[16]; - /* 0x090 */ Bit8u hd1_info[16]; - /* 0x0a0 */ Bit8u pad2[0x1e0 - 0xa0]; - /* 0x1e0 */ Bit32u memory_size_ext; - /* 0x1e4 */ Bit8u pad3[0x1f1 - 0x1e4]; - /* 0x1f1 */ Bit8u setup_sects; - /* 0x1f2 */ Bit16u mount_root_rdonly; - /* 0x1f4 */ Bit16u sys_size; - /* 0x1f6 */ Bit16u swap_dev; - /* 0x1f8 */ Bit16u ramdisk_flags; - /* 0x1fa */ Bit16u vga_mode; - /* 0x1fc */ Bit16u orig_root_dev; - /* 0x1fe */ Bit16u bootsect_magic; - /* 0x200 */ Bit8u pad4[0x210 - 0x200]; - /* 0x210 */ Bit32u loader_type; - /* 0x214 */ Bit32u kernel_start; - /* 0x218 */ Bit32u initrd_start; - /* 0x21c */ Bit32u initrd_size; - /* 0x220 */ Bit8u pad5[0x400 - 0x220]; - /* 0x400 */ struct gdt_entry gdt[128]; - /* 0x800 */ Bit8u commandline[2048]; -}; - - static void -bx_load_linux_setup_params( Bit32u initrd_start, Bit32u initrd_size ) -{ - BX_MEM_C *mem = BX_MEM(0); - struct linux_setup_params *params = - (struct linux_setup_params *) &mem->vector[0x00090000]; - - memset( params, '\0', sizeof(*params) ); - - /* Video settings (standard VGA) */ - params->orig_x = 0; - params->orig_y = 0; - params->orig_video_page = 0; - params->orig_video_mode = 3; - params->orig_video_cols = 80; - params->orig_video_lines = 25; - params->orig_video_points = 16; - params->orig_video_isVGA = 1; - params->orig_video_ega_bx = 3; - - /* Memory size (total mem - 1MB, in KB) */ - params->memory_size_ext = (mem->megabytes - 1) * 1024; - - /* Boot parameters */ - params->loader_type = 1; - params->bootsect_magic = 0xaa55; - params->mount_root_rdonly = 0; - params->orig_root_dev = 0x0100; - params->initrd_start = initrd_start; - params->initrd_size = initrd_size; - - /* Initial GDT */ - params->gdt[2].high = 0x00cf9a00; - params->gdt[2].low = 0x0000ffff; - params->gdt[3].high = 0x00cf9200; - params->gdt[3].low = 0x0000ffff; -} - - void -bx_load_linux_hack(void) -{ -#ifndef BX_USE_VMX - Bit32u initrd_start = 0, initrd_size = 0; - - // The RESET function will have been called first. - // Set CPU and memory features which are assumed at this point. - - // Load Linux kernel image - bx_load_kernel_image( bx_options.load32bitOSImage.Opath->getptr (), 0x100000 ); - - // Load initial ramdisk image if requested - if ( bx_options.load32bitOSImage.Oinitrd->getptr () ) - { - initrd_start = 0x00800000; /* FIXME: load at top of memory */ - initrd_size = bx_load_kernel_image( bx_options.load32bitOSImage.Oinitrd->getptr (), initrd_start ); - } - - // Setup Linux startup parameters buffer - bx_load_linux_setup_params( initrd_start, initrd_size ); -#endif - - // Enable A20 line - BX_SET_ENABLE_A20( 1 ); - - // Setup PICs the way Linux likes it - BX_OUTP( 0x20, 0x11, 1 ); - BX_OUTP( 0xA0, 0x11, 1 ); - BX_OUTP( 0x21, 0x20, 1 ); - BX_OUTP( 0xA1, 0x28, 1 ); - BX_OUTP( 0x21, 0x04, 1 ); - BX_OUTP( 0xA1, 0x02, 1 ); - BX_OUTP( 0x21, 0x01, 1 ); - BX_OUTP( 0xA1, 0x01, 1 ); - BX_OUTP( 0x21, 0xFF, 1 ); - BX_OUTP( 0xA1, 0xFB, 1 ); - -#ifndef BX_USE_VMX - // Disable interrupts and NMIs - BX_CPU(0)->clear_IF (); -#endif - - BX_OUTP( 0x70, 0x80, 1 ); - -#ifndef BX_USE_VMX - // Enter protected mode - // Fixed by george (kyriazis at nvidia.com) - // BX_CPU(0)->cr0.pe = 1; - // BX_CPU(0)->cr0.val32 |= 0x01; - - BX_CPU(0)->SetCR0(BX_CPU(0)->cr0.val32 | 0x01); - - // load esi with real_mode - BX_CPU(0)->gen_reg[BX_32BIT_REG_ESI].dword.erx = 0x90000; - - // Set up initial GDT - BX_CPU(0)->gdtr.limit = 0x400; - BX_CPU(0)->gdtr.base = 0x00090400; - - // Jump to protected mode entry point - BX_CPU(0)->jump_protected( NULL, 0x10, 0x00100000 ); -#endif -} - - void -bx_load_null_kernel_hack(void) -{ -#ifndef BX_USE_VMX - // The RESET function will have been called first. - // Set CPU and memory features which are assumed at this point. - - bx_load_kernel_image(bx_options.load32bitOSImage.Opath->getptr (), 0x100000); - - // EIP deltas - BX_CPU(0)->prev_eip = - BX_CPU(0)->dword.eip = 0x00100000; - - // CS deltas - BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.base = 0x00000000; - BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.limit = 0xFFFFF; - BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; - BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; // page gran - BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1; // 32bit - - // DS deltas - BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.base = 0x00000000; - BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.limit = 0xFFFFF; - BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled = 0xFFFFFFFF; - BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.g = 1; // page gran - BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.d_b = 1; // 32bit - - // CR0 deltas - BX_CPU(0)->cr0.pe = 1; // protected mode -#endif // BX_USE_VMX -} - - Bit32u -bx_load_kernel_image(char *path, Bit32u paddr) -{ - struct stat stat_buf; - int fd, ret; - unsigned long size, offset; - Bit32u page_size; - - // read in ROM BIOS image file - fd = open(path, O_RDONLY -#ifdef O_BINARY - | O_BINARY -#endif - ); - if (fd < 0) { - BX_INFO(( "load_kernel_image: couldn't open image file '%s'.", path )); - BX_EXIT(1); - } - ret = fstat(fd, &stat_buf); - if (ret) { - BX_INFO(( "load_kernel_image: couldn't stat image file '%s'.", path )); - BX_EXIT(1); - } - - size = stat_buf.st_size; - page_size = ((Bit32u)size + 0xfff) & ~0xfff; - - BX_MEM_C *mem = BX_MEM(0); - if ( (paddr + size) > mem->len ) { - BX_INFO(( "load_kernel_image: address range > physical memsize!" )); - BX_EXIT(1); - } - - offset = 0; - while (size > 0) { - ret = read(fd, (bx_ptr_t) &mem->vector[paddr + offset], size); - if (ret <= 0) { - BX_INFO(( "load_kernel_image: read failed on image" )); - BX_EXIT(1); - } - size -= ret; - offset += ret; - } - close(fd); - BX_INFO(( "#(%u) load_kernel_image: '%s', size=%u read into memory at %08x", - BX_SIM_ID, path, - (unsigned) stat_buf.st_size, - (unsigned) paddr )); - - return page_size; -} diff --git a/tools/ioemu/iodev/logio.cc b/tools/ioemu/iodev/logio.cc deleted file mode 100644 index 2b79719a2c..0000000000 --- a/tools/ioemu/iodev/logio.cc +++ /dev/null @@ -1,631 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: logio.cc,v 1.42 2003/08/24 10:30:07 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - -#include "bochs.h" -#include -#include "state_file.h" - -#if BX_WITH_CARBON -#include -#endif - -// Just for the iofunctions - - -int Allocio=0; - -void -iofunctions::flush(void) { - if(logfd && magic == MAGIC_LOGNUM) { - fflush(logfd); - } -} - -void -iofunctions::init(void) { - // iofunctions methods must not be called before this magic - // number is set. - magic=MAGIC_LOGNUM; - - // sets the default logprefix - strcpy(logprefix,"%t%e%d"); - n_logfn = 0; - init_log(stderr); - log = new logfunc_t(this); - log->put("IO"); - log->settype(IOLOG); - log->ldebug ("Init(log file: '%s').",logfn); -} - -void -iofunctions::add_logfn (logfunc_t *fn) -{ - assert (n_logfn < MAX_LOGFNS); - logfn_list[n_logfn++] = fn; -} - -void -iofunctions::set_log_action (int loglevel, int action) -{ - for (int i=0; isetonoff(loglevel, action); -} - -void -iofunctions::init_log(const char *fn) -{ - assert (magic==MAGIC_LOGNUM); - // use newfd/newfn so that we can log the message to the OLD log - // file descriptor. - FILE *newfd = stderr; - char *newfn = "/dev/stderr"; - if( strcmp( fn, "-" ) != 0 ) { - newfd = fopen(fn, "w"); - if(newfd != NULL) { - newfn = strdup(fn); - log->ldebug ("Opened log file '%s'.", fn ); - } else { - // in constructor, genlog might not exist yet, so do it the safe way. - log->error("Couldn't open log file: %s, using stderr instead", fn); - newfd = stderr; - } - } - logfd = newfd; - logfn = newfn; -} - -void -iofunctions::init_log(FILE *fs) -{ - assert (magic==MAGIC_LOGNUM); - logfd = fs; - - if(fs == stderr) { - logfn = "/dev/stderr"; - } else if(fs == stdout) { - logfn = "/dev/stdout"; - } else { - logfn = "(unknown)"; - } - -} - -void -iofunctions::init_log(int fd) -{ - assert (magic==MAGIC_LOGNUM); - FILE *tmpfd; - if( (tmpfd = fdopen(fd,"w")) == NULL ) { - log->panic("Couldn't open fd %d as a stream for writing", fd); - return; - } - - init_log(tmpfd); - return; -}; - -// all other functions may use genlog safely. -#define LOG_THIS genlog-> - -// This converts the option string to a printf style string with the following args: -// 1. timer, 2. event, 3. cpu0 eip, 4. device -void -iofunctions::set_log_prefix(const char* prefix) { - - strcpy(logprefix,prefix); -} - -// iofunctions::out( class, level, prefix, fmt, ap) -// DO NOT nest out() from ::info() and the like. -// fmt and ap retained for direct printinf from iofunctions only! - -void -iofunctions::out(int f, int l, const char *prefix, const char *fmt, va_list ap) -{ - char c=' ', *s; - assert (magic==MAGIC_LOGNUM); - assert (this != NULL); - assert (logfd != NULL); - - //if( showtick ) - // fprintf(logfd, "%011lld", bx_pc_system.time_ticks()); - - switch(l) { - case LOGLEV_INFO: c='i'; break; - case LOGLEV_PANIC: c='p'; break; - case LOGLEV_PASS: c='s'; break; - case LOGLEV_ERROR: c='e'; break; - case LOGLEV_DEBUG: c='d'; break; - default: break; - } - //fprintf(logfd, "-%c",c); - - //if(prefix != NULL) - // fprintf(logfd, "%s ", prefix); - - s=logprefix; - while(*s) { - switch(*s) { - case '%': - if(*(s+1))s++; - else break; - switch(*s) { - case 'd': - fprintf(logfd, "%s", prefix==NULL?"":prefix); - break; - case 't': - fprintf(logfd, "%011lld", bx_pc_system.time_ticks()); - break; -#ifndef BX_USE_VMX - case 'i': - fprintf(logfd, "%08x", BX_CPU(0)==NULL?0:BX_CPU(0)->dword.eip); - break; -#endif - case 'e': - fprintf(logfd, "%c", c); - break; - case '%': - fprintf(logfd,"%%"); - break; - default: - fprintf(logfd,"%%%c",*s); - } - break; - default : - fprintf(logfd,"%c",*s); - } - s++; - } - - fprintf(logfd," "); - - if(l==LOGLEV_PANIC) - fprintf(logfd, ">>PANIC<< "); - if(l==LOGLEV_PASS) - fprintf(logfd, ">>PASS<< "); - - vfprintf(logfd, fmt, ap); - fprintf(logfd, "\n"); - fflush(logfd); - - return; -} - -iofunctions::iofunctions(FILE *fs) -{ - init(); - init_log(fs); -} - -iofunctions::iofunctions(const char *fn) -{ - init(); - init_log(fn); -} - -iofunctions::iofunctions(int fd) -{ - init(); - init_log(fd); -} - -iofunctions::iofunctions(void) -{ - this->init(); -} - -iofunctions::~iofunctions(void) -{ - // flush before erasing magic number, or flush does nothing. - this->flush(); - this->magic=0; -} - -#define LOG_THIS genlog-> - -int logfunctions::default_onoff[N_LOGLEV] = { - ACT_IGNORE, // ignore debug - ACT_REPORT, // report info - ACT_REPORT, // report error -#if BX_WITH_WX - ACT_ASK, // on panic, ask user what to do -#else - ACT_FATAL, // on panic, quit -#endif - ACT_FATAL -}; - -logfunctions::logfunctions(void) -{ - prefix = NULL; - put(" "); - settype(GENLOG); - if (io == NULL && Allocio == 0) { - Allocio = 1; - io = new iofunc_t(stderr); - } - setio(io); - // BUG: unfortunately this can be called before the bochsrc is read, - // which means that the bochsrc has no effect on the actions. - for (int i=0; iprefix ) - { - free(this->prefix); - this->prefix = NULL; - } -} - -void -logfunctions::setio(iofunc_t *i) -{ - // add pointer to iofunction object to use - this->logio = i; - // give iofunction a pointer to me - i->add_logfn (this); -} - -void -logfunctions::put(char *p) -{ - char *tmpbuf; - tmpbuf=strdup("[ ]");// if we ever have more than 32 chars, - // we need to rethink this - - if ( tmpbuf == NULL) - { - return ; /* allocation not successful */ - } - if ( this->prefix != NULL ) - { - free(this->prefix); /* free previously allocated memory */ - this->prefix = NULL; - } - int len=strlen(p); - for(int i=1;iprefix=tmpbuf; -} - -void -logfunctions::settype(int t) -{ - type=t; -} - -void -logfunctions::info(const char *fmt, ...) -{ - va_list ap; - - assert (this != NULL); - assert (this->logio != NULL); - - if(!onoff[LOGLEV_INFO]) return; - - va_start(ap, fmt); - this->logio->out(this->type,LOGLEV_INFO,this->prefix, fmt, ap); - if (onoff[LOGLEV_INFO] == ACT_ASK) - ask (LOGLEV_INFO, this->prefix, fmt, ap); - if (onoff[LOGLEV_INFO] == ACT_FATAL) - fatal (this->prefix, fmt, ap, 1); - va_end(ap); - -} - -void -logfunctions::error(const char *fmt, ...) -{ - va_list ap; - - assert (this != NULL); - assert (this->logio != NULL); - - if(!onoff[LOGLEV_ERROR]) return; - - va_start(ap, fmt); - this->logio->out(this->type,LOGLEV_ERROR,this->prefix, fmt, ap); - if (onoff[LOGLEV_ERROR] == ACT_ASK) - ask (LOGLEV_ERROR, this->prefix, fmt, ap); - if (onoff[LOGLEV_ERROR] == ACT_FATAL) - fatal (this->prefix, fmt, ap, 1); - va_end(ap); -} - -void -logfunctions::panic(const char *fmt, ...) -{ - va_list ap; - - assert (this != NULL); - assert (this->logio != NULL); - - // Special case for panics since they are so important. Always print - // the panic to the log, no matter what the log action says. - //if(!onoff[LOGLEV_PANIC]) return; - - va_start(ap, fmt); - this->logio->out(this->type,LOGLEV_PANIC,this->prefix, fmt, ap); - - // This fixes a funny bug on linuxppc where va_list is no pointer but a struct - va_end(ap); - va_start(ap, fmt); - - if (onoff[LOGLEV_PANIC] == ACT_ASK) - ask (LOGLEV_PANIC, this->prefix, fmt, ap); - if (onoff[LOGLEV_PANIC] == ACT_FATAL) - fatal (this->prefix, fmt, ap, 1); - va_end(ap); -} - -void -logfunctions::pass(const char *fmt, ...) -{ - va_list ap; - - assert (this != NULL); - assert (this->logio != NULL); - - // Special case for panics since they are so important. Always print - // the panic to the log, no matter what the log action says. - //if(!onoff[LOGLEV_PASS]) return; - - va_start(ap, fmt); - this->logio->out(this->type,LOGLEV_PASS,this->prefix, fmt, ap); - - // This fixes a funny bug on linuxppc where va_list is no pointer but a struct - va_end(ap); - va_start(ap, fmt); - - if (onoff[LOGLEV_PASS] == ACT_ASK) - ask (LOGLEV_PASS, this->prefix, fmt, ap); - if (onoff[LOGLEV_PASS] == ACT_FATAL) - fatal (this->prefix, fmt, ap, 101); - va_end(ap); -} - -void -logfunctions::ldebug(const char *fmt, ...) -{ - va_list ap; - - assert (this != NULL); - assert (this->logio != NULL); - - if(!onoff[LOGLEV_DEBUG]) return; - - va_start(ap, fmt); - this->logio->out(this->type,LOGLEV_DEBUG,this->prefix, fmt, ap); - if (onoff[LOGLEV_DEBUG] == ACT_ASK) - ask (LOGLEV_DEBUG, this->prefix, fmt, ap); - if (onoff[LOGLEV_DEBUG] == ACT_FATAL) - fatal (this->prefix, fmt, ap, 1); - va_end(ap); -} - -void -logfunctions::ask (int level, const char *prefix, const char *fmt, va_list ap) -{ - // Guard against reentry on ask() function. The danger is that some - // function that's called within ask() could trigger another - // BX_PANIC that could call ask() again, leading to infinite - // recursion and infinite asks. - static char in_ask_already = 0; - char buf1[1024]; - if (in_ask_already) { - fprintf (stderr, "logfunctions::ask() should not reenter!!\n"); - return; - } - in_ask_already = 1; - vsprintf (buf1, fmt, ap); - // FIXME: facility set to 0 because it's unknown. - - // update vga screen. This is useful because sometimes useful messages - // are printed on the screen just before a panic. It's also potentially - // dangerous if this function calls ask again... That's why I added - // the reentry check above. - if (SIM->get_init_done()) DEV_vga_refresh(); - -#if !BX_EXTERNAL_DEBUGGER - // ensure the text screen is showing - SIM->set_display_mode (DISP_MODE_CONFIG); - int val = SIM->log_msg (prefix, level, buf1); - switch (val) - { - case BX_LOG_ASK_CHOICE_CONTINUE: - break; - case BX_LOG_ASK_CHOICE_CONTINUE_ALWAYS: - // user said continue, and don't "ask" for this facility again. - setonoff (level, ACT_REPORT); - break; - case BX_LOG_ASK_CHOICE_DIE: - bx_user_quit = 1; - in_ask_already = 0; // because fatal will longjmp out - fatal (prefix, fmt, ap, 1); - // should never get here - BX_PANIC (("in ask(), fatal() should never return!")); - break; - case BX_LOG_ASK_CHOICE_DUMP_CORE: - fprintf (stderr, "User chose to dump core...\n"); -#if BX_HAVE_ABORT - abort (); -#else - // do something highly illegal that should kill the process. - // Hey, this is fun! - { - char *crashptr = (char *)0; char c = *crashptr; - } - fprintf (stderr, "Sorry, I couldn't find your abort() function. Exiting."); - exit (0); -#endif -#if BX_DEBUGGER - case BX_LOG_ASK_CHOICE_ENTER_DEBUG: - // user chose debugger. To "drop into the debugger" we just set the - // interrupt_requested bit and continue execution. Before the next - // instruction, it should notice the user interrupt and return to - // the debugger. - bx_guard.interrupt_requested = 1; - break; -#endif - default: - // this happens if panics happen before the callback is initialized - // in gui/control.cc. - fprintf (stderr, "WARNING: log_msg returned unexpected value %d\n", val); - } -#else - // external debugger ask code goes here -#endif - // return to simulation mode - SIM->set_display_mode (DISP_MODE_SIM); - in_ask_already = 0; -} - -#if BX_WITH_CARBON -/* Panic button to display fatal errors. - Completely self contained, can't rely on carbon.cc being available */ -static void carbonFatalDialog(const char *error, const char *exposition) -{ - DialogRef alertDialog; - CFStringRef cfError; - CFStringRef cfExposition; - DialogItemIndex index; - AlertStdCFStringAlertParamRec alertParam = {0}; - - // Init libraries - InitCursor(); - // Assemble dialog - cfError = CFStringCreateWithCString(NULL, error, kCFStringEncodingASCII); - if(exposition != NULL) - { - cfExposition = CFStringCreateWithCString(NULL, exposition, kCFStringEncodingASCII); - } - else { cfExposition = NULL; } - alertParam.version = kStdCFStringAlertVersionOne; - alertParam.defaultText = CFSTR("Quit"); - alertParam.position = kWindowDefaultPosition; - alertParam.defaultButton = kAlertStdAlertOKButton; - // Display Dialog - CreateStandardAlert( - kAlertStopAlert, - cfError, - cfExposition, /* can be NULL */ - &alertParam, /* can be NULL */ - &alertDialog); - RunStandardAlert( alertDialog, NULL, &index); - // Cleanup - CFRelease( cfError ); - if( cfExposition != NULL ) { CFRelease( cfExposition ); } -} -#endif - -void -logfunctions::fatal (const char *prefix, const char *fmt, va_list ap, int exit_status) -{ - bx_atexit(); -#if BX_WITH_CARBON - if(!isatty(STDIN_FILENO) && !SIM->get_init_done()) - { - char buf1[1024]; - char buf2[1024]; - vsprintf (buf1, fmt, ap); - sprintf (buf2, "Bochs startup error\n%s", buf1); - carbonFatalDialog(buf2, - "For more information, try running Bochs within Terminal by clicking on \"bochs.scpt\"."); - } -#endif -#if !BX_WITH_WX - static char *divider = "========================================================================"; - fprintf (stderr, "%s\n", divider); - fprintf (stderr, "Bochs is exiting with the following message:\n"); - fprintf (stderr, "%s ", prefix); - vfprintf (stderr, fmt, ap); - fprintf (stderr, "\n%s\n", divider); -#endif -#if 0 && defined(WIN32) -#error disabled because it is not working yet! - // wait for a keypress before quitting. Depending on how bochs is - // installed, the console window can disappear before the user has - // a chance to read the final message. - fprintf (stderr, "\n\nPress Enter to exit...\n"); - char buf[8]; - fgets (buf, 8, stdin); -#endif -#if !BX_DEBUGGER - BX_EXIT(exit_status); -#else - static bx_bool dbg_exit_called = 0; - if (dbg_exit_called == 0) { - dbg_exit_called = 1; - bx_dbg_exit(exit_status); - } -#endif - // not safe to use BX_* log functions in here. - fprintf (stderr, "fatal() should never return, but it just did\n"); -} - -iofunc_t *io = NULL; -logfunc_t *genlog = NULL; - -void bx_center_print (FILE *file, char *line, int maxwidth) -{ - int imax; - int len = strlen(line); - if (len > maxwidth) - BX_PANIC (("bx_center_print: line is too long: '%s'", line)); - imax = (maxwidth - len) >> 1; - for (int i=0; i -// Copyright (C) 2004 Intel Corp -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -#include "bochs.h" -#include -#include "state_file.h" - -#ifdef HAVE_LOCALE_H -#include -#endif - -extern "C" { -#include -} - -#if BX_GUI_SIGHANDLER -bx_bool bx_gui_sighandler = 0; -#endif - -// single processor simulation, so there's one of everything -BOCHSAPI BX_CPU_C bx_cpu; -BOCHSAPI BX_MEM_C bx_mem; - -int xc_handle; -int bochsrc_include_count = 0; - -// some prototypes from iodev/ -// I want to stay away from including iodev/iodev.h here -Bit32u bx_unmapped_io_read_handler(Bit32u address, unsigned io_len); -void bx_unmapped_io_write_handler(Bit32u address, Bit32u value, - unsigned io_len); -void bx_close_harddrive(void); - - -void bx_init_bx_dbg (void); -static char *divider = "========================================================================"; -static logfunctions thePluginLog; -logfunctions *pluginlog = &thePluginLog; - -bx_startup_flags_t bx_startup_flags; -bx_bool bx_user_quit; - -/* typedefs */ - -#define LOG_THIS genlog-> - -#if ( BX_PROVIDE_DEVICE_MODELS==1 ) -bx_pc_system_c bx_pc_system; -class state_file state_stuff("state_file.out", "options"); -#endif - -bx_debug_t bx_dbg; - -bx_options_t bx_options; // initialized in bx_init_options() -char *bochsrc_filename = NULL; - -static Bit32s parse_line_unformatted(char *context, char *line); -static Bit32s parse_line_formatted(char *context, int num_params, char *params[]); -static int parse_bochsrc(char *rcfile); - -static Bit64s -bx_param_handler (bx_param_c *param, int set, Bit64s val) -{ - bx_id id = param->get_id (); - switch (id) { - case BXP_VGA_UPDATE_INTERVAL: - // if after init, notify the vga device to change its timer. - if (set && SIM->get_init_done ()) - DEV_vga_set_update_interval (val); - break; - case BXP_MOUSE_ENABLED: - // if after init, notify the GUI - if (set && SIM->get_init_done ()) { - bx_gui->mouse_enabled_changed (val!=0); - DEV_mouse_enabled_changed (val!=0); - } - break; - case BXP_NE2K_PRESENT: - if (set) { - int enable = (val != 0); - SIM->get_param (BXP_NE2K_IOADDR)->set_enabled (enable); - SIM->get_param (BXP_NE2K_IRQ)->set_enabled (enable); - SIM->get_param (BXP_NE2K_MACADDR)->set_enabled (enable); - SIM->get_param (BXP_NE2K_ETHMOD)->set_enabled (enable); - SIM->get_param (BXP_NE2K_ETHDEV)->set_enabled (enable); - SIM->get_param (BXP_NE2K_SCRIPT)->set_enabled (enable); - } - break; - case BXP_LOAD32BITOS_WHICH: - if (set) { - int enable = (val != Load32bitOSNone); - SIM->get_param (BXP_LOAD32BITOS_PATH)->set_enabled (enable); - SIM->get_param (BXP_LOAD32BITOS_IOLOG)->set_enabled (enable); - SIM->get_param (BXP_LOAD32BITOS_INITRD)->set_enabled (enable); - } - break; - case BXP_ATA0_MASTER_STATUS: - case BXP_ATA0_SLAVE_STATUS: - case BXP_ATA1_MASTER_STATUS: - case BXP_ATA1_SLAVE_STATUS: - case BXP_ATA2_MASTER_STATUS: - case BXP_ATA2_SLAVE_STATUS: - case BXP_ATA3_MASTER_STATUS: - case BXP_ATA3_SLAVE_STATUS: - if ((set) && (SIM->get_init_done ())) { - Bit8u device = id - BXP_ATA0_MASTER_STATUS; - Bit32u handle = DEV_hd_get_device_handle (device/2, device%2); - DEV_hd_set_cd_media_status(handle, val == BX_INSERTED); - bx_gui->update_drive_status_buttons (); - } - break; - case BXP_FLOPPYA_TYPE: - if ((set) && (!SIM->get_init_done ())) { - bx_options.floppya.Odevtype->set (val); - } - break; - case BXP_FLOPPYA_STATUS: - if ((set) && (SIM->get_init_done ())) { - DEV_floppy_set_media_status(0, val == BX_INSERTED); - bx_gui->update_drive_status_buttons (); - } - break; - case BXP_FLOPPYB_TYPE: - if ((set) && (!SIM->get_init_done ())) { - bx_options.floppyb.Odevtype->set (val); - } - break; - case BXP_FLOPPYB_STATUS: - if ((set) && (SIM->get_init_done ())) { - DEV_floppy_set_media_status(1, val == BX_INSERTED); - bx_gui->update_drive_status_buttons (); - } - break; - case BXP_KBD_PASTE_DELAY: - if ((set) && (SIM->get_init_done ())) { - DEV_kbd_paste_delay_changed (); - } - break; - - case BXP_ATA0_MASTER_MODE: - case BXP_ATA0_SLAVE_MODE: - case BXP_ATA1_MASTER_MODE: - case BXP_ATA1_SLAVE_MODE: - case BXP_ATA2_MASTER_MODE: - case BXP_ATA2_SLAVE_MODE: - case BXP_ATA3_MASTER_MODE: - case BXP_ATA3_SLAVE_MODE: - if (set) { - int device = id - BXP_ATA0_MASTER_MODE; - switch (val) { - case BX_ATA_MODE_UNDOABLE: - case BX_ATA_MODE_VOLATILE: - //case BX_ATA_MODE_Z_UNDOABLE: - //case BX_ATA_MODE_Z_VOLATILE: - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_JOURNAL + device))->set_enabled (1); - break; - default: - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_JOURNAL + device))->set_enabled (0); - } - } - break; - - case BXP_ATA0_MASTER_TYPE: - case BXP_ATA0_SLAVE_TYPE: - case BXP_ATA1_MASTER_TYPE: - case BXP_ATA1_SLAVE_TYPE: - case BXP_ATA2_MASTER_TYPE: - case BXP_ATA2_SLAVE_TYPE: - case BXP_ATA3_MASTER_TYPE: - case BXP_ATA3_SLAVE_TYPE: - if (set) { - int device = id - BXP_ATA0_MASTER_TYPE; - switch (val) { - case BX_ATA_DEVICE_DISK: - SIM->get_param_num ((bx_id)(BXP_ATA0_MASTER_PRESENT + device))->set (1); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_MODE + device))->set_enabled (1); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_PATH + device))->set_enabled (1); - //SIM->get_param ((bx_id)(BXP_ATA0_MASTER_JOURNAL + device))->set_enabled (1); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_CYLINDERS + device))->set_enabled (1); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_HEADS + device))->set_enabled (1); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_SPT + device))->set_enabled (1); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_STATUS + device))->set_enabled (0); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_MODEL + device))->set_enabled (1); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_BIOSDETECT + device))->set_enabled (1); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_TRANSLATION + device))->set_enabled (1); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_PATH + device))->set_runtime_param (0); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_STATUS + device))->set_runtime_param (0); - break; - case BX_ATA_DEVICE_CDROM: - SIM->get_param_num ((bx_id)(BXP_ATA0_MASTER_PRESENT + device))->set (1); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_MODE + device))->set_enabled (0); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_PATH + device))->set_enabled (1); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_JOURNAL + device))->set_enabled (0); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_CYLINDERS + device))->set_enabled (0); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_HEADS + device))->set_enabled (0); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_SPT + device))->set_enabled (0); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_STATUS + device))->set_enabled (1); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_MODEL + device))->set_enabled (1); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_BIOSDETECT + device))->set_enabled (1); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_TRANSLATION + device))->set_enabled (0); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_PATH + device))->set_runtime_param (1); - SIM->get_param ((bx_id)(BXP_ATA0_MASTER_STATUS + device))->set_runtime_param (1); - break; - } - } - break; - default: - BX_PANIC (("bx_param_handler called with unknown id %d", id)); - return -1; - } - return val; -} - -char *bx_param_string_handler (bx_param_string_c *param, int set, char *val, int maxlen) -{ - bx_id id = param->get_id (); - - int empty = 0; - if ((strlen(val) < 1) || !strcmp ("none", val)) { - empty = 1; - val = "none"; - } - switch (id) { - case BXP_FLOPPYA_PATH: - if (set==1) { - if (SIM->get_init_done ()) { - if (empty) { - DEV_floppy_set_media_status(0, 0); - bx_gui->update_drive_status_buttons (); - } else { - if (!SIM->get_param_num(BXP_FLOPPYA_TYPE)->get_enabled()) { - BX_ERROR(("Cannot add a floppy drive at runtime")); - bx_options.floppya.Opath->set ("none"); - } - } - if ((DEV_floppy_present()) && - (SIM->get_param_num(BXP_FLOPPYA_STATUS)->get () == BX_INSERTED)) { - // tell the device model that we removed, then inserted the disk - DEV_floppy_set_media_status(0, 0); - DEV_floppy_set_media_status(0, 1); - } - } else { - SIM->get_param_num(BXP_FLOPPYA_DEVTYPE)->set_enabled (!empty); - SIM->get_param_num(BXP_FLOPPYA_TYPE)->set_enabled (!empty); - SIM->get_param_num(BXP_FLOPPYA_STATUS)->set_enabled (!empty); - } - } - break; - case BXP_FLOPPYB_PATH: - if (set==1) { - if (SIM->get_init_done ()) { - if (empty) { - DEV_floppy_set_media_status(1, 0); - bx_gui->update_drive_status_buttons (); - } else { - if (!SIM->get_param_num(BXP_FLOPPYB_TYPE)->get_enabled ()) { - BX_ERROR(("Cannot add a floppy drive at runtime")); - bx_options.floppyb.Opath->set ("none"); - } - } - if ((DEV_floppy_present()) && - (SIM->get_param_num(BXP_FLOPPYB_STATUS)->get () == BX_INSERTED)) { - // tell the device model that we removed, then inserted the disk - DEV_floppy_set_media_status(1, 0); - DEV_floppy_set_media_status(1, 1); - } - } else { - SIM->get_param_num(BXP_FLOPPYB_DEVTYPE)->set_enabled (!empty); - SIM->get_param_num(BXP_FLOPPYB_TYPE)->set_enabled (!empty); - SIM->get_param_num(BXP_FLOPPYB_STATUS)->set_enabled (!empty); - } - } - break; - - case BXP_ATA0_MASTER_PATH: - case BXP_ATA0_SLAVE_PATH: - case BXP_ATA1_MASTER_PATH: - case BXP_ATA1_SLAVE_PATH: - case BXP_ATA2_MASTER_PATH: - case BXP_ATA2_SLAVE_PATH: - case BXP_ATA3_MASTER_PATH: - case BXP_ATA3_SLAVE_PATH: - if (set==1) { - if (SIM->get_init_done ()) { - - Bit8u device = id - BXP_ATA0_MASTER_PATH; - Bit32u handle = DEV_hd_get_device_handle(device/2, device%2); - - if (empty) { - DEV_hd_set_cd_media_status(handle, 0); - bx_gui->update_drive_status_buttons (); - } else { - if (!SIM->get_param_num((bx_id)(BXP_ATA0_MASTER_PRESENT + device))->get ()) { - BX_ERROR(("Cannot add a cdrom drive at runtime")); - bx_options.atadevice[device/2][device%2].Opresent->set (0); - } - if (SIM->get_param_num((bx_id)(BXP_ATA0_MASTER_TYPE + device))->get () != BX_ATA_DEVICE_CDROM) { - BX_ERROR(("Device is not a cdrom drive")); - bx_options.atadevice[device/2][device%2].Opresent->set (0); - } - } - if (DEV_hd_present() && - (SIM->get_param_num((bx_id)(BXP_ATA0_MASTER_STATUS + device))->get () == BX_INSERTED) && - (SIM->get_param_num((bx_id)(BXP_ATA0_MASTER_TYPE + device))->get () == BX_ATA_DEVICE_CDROM)) { - // tell the device model that we removed, then inserted the cd - DEV_hd_set_cd_media_status(handle, 0); - DEV_hd_set_cd_media_status(handle, 1); - } - } - } - break; - - case BXP_SCREENMODE: - if (set==1) { - BX_INFO (("Screen mode changed to %s", val)); - } - break; - default: - BX_PANIC (("bx_string_handler called with unexpected parameter %d", param->get_id())); - } - return val; -} - -static int -bx_param_enable_handler (bx_param_c *param, int val) -{ - bx_id id = param->get_id (); - switch (id) { - case BXP_ATA0_MASTER_STATUS: - case BXP_ATA0_SLAVE_STATUS: - case BXP_ATA1_MASTER_STATUS: - case BXP_ATA1_SLAVE_STATUS: - case BXP_ATA2_MASTER_STATUS: - case BXP_ATA2_SLAVE_STATUS: - case BXP_ATA3_MASTER_STATUS: - case BXP_ATA3_SLAVE_STATUS: - if (val != 0) { - Bit8u device = id - BXP_ATA0_MASTER_STATUS; - - switch (SIM->get_param_enum ((bx_id)(BXP_ATA0_MASTER_TYPE + device))->get()) { - case BX_ATA_DEVICE_CDROM: - return (1); - break; - } - } - return (0); - break; - - case BXP_ATA0_MASTER_JOURNAL: - case BXP_ATA0_SLAVE_JOURNAL: - case BXP_ATA1_MASTER_JOURNAL: - case BXP_ATA1_SLAVE_JOURNAL: - case BXP_ATA2_MASTER_JOURNAL: - case BXP_ATA2_SLAVE_JOURNAL: - case BXP_ATA3_MASTER_JOURNAL: - case BXP_ATA3_SLAVE_JOURNAL: - if (val != 0) { - Bit8u device = id - BXP_ATA0_MASTER_JOURNAL; - - switch (SIM->get_param_enum ((bx_id)(BXP_ATA0_MASTER_TYPE + device))->get()) { - case BX_ATA_DEVICE_DISK: - switch (SIM->get_param_enum ((bx_id)(BXP_ATA0_MASTER_MODE + device))->get()) { - case BX_ATA_MODE_UNDOABLE: - case BX_ATA_MODE_VOLATILE: - //case BX_ATA_MODE_Z_UNDOABLE: - //case BX_ATA_MODE_Z_VOLATILE: - return (1); - break; - } - } - } - return (0); - break; - - default: - BX_PANIC (("bx_param_handler called with unknown id %d", id)); - } - return val; -} - - - -void bx_init_options () -{ - int i; - bx_list_c *menu; - bx_list_c *deplist; - char name[1024], descr[1024], label[1024]; - - memset (&bx_options, 0, sizeof(bx_options)); - - // quick start option, set by command line arg - new bx_param_enum_c (BXP_BOCHS_START, - "Bochs start types", - "Bochs start types", - bochs_start_names, - BX_RUN_START, - BX_QUICK_START); - - // floppya - bx_options.floppya.Opath = new bx_param_filename_c (BXP_FLOPPYA_PATH, - "floppya:path", - "Pathname of first floppy image file or device. If you're booting from floppy, this should be a bootable floppy.", - "", BX_PATHNAME_LEN); - bx_options.floppya.Opath->set_ask_format ("Enter new filename, or 'none' for no disk: [%s] "); - bx_options.floppya.Opath->set_label ("First floppy image/device"); - bx_options.floppya.Odevtype = new bx_param_enum_c (BXP_FLOPPYA_DEVTYPE, - "floppya:devtype", - "Type of floppy drive", - floppy_type_names, - BX_FLOPPY_NONE, - BX_FLOPPY_NONE); - bx_options.floppya.Otype = new bx_param_enum_c (BXP_FLOPPYA_TYPE, - "floppya:type", - "Type of floppy disk", - floppy_type_names, - BX_FLOPPY_NONE, - BX_FLOPPY_NONE); - bx_options.floppya.Otype->set_ask_format ("What type of floppy disk? [%s] "); - bx_options.floppya.Ostatus = new bx_param_enum_c (BXP_FLOPPYA_STATUS, - "Is floppya inserted", - "Inserted or ejected", - floppy_status_names, - BX_INSERTED, - BX_EJECTED); - bx_options.floppya.Ostatus->set_ask_format ("Is the floppy inserted or ejected? [%s] "); - bx_options.floppya.Opath->set_format ("%s"); - bx_options.floppya.Otype->set_format ("size=%s"); - bx_options.floppya.Ostatus->set_format ("%s"); - bx_param_c *floppya_init_list[] = { - // if the order "path,type,status" changes, corresponding changes must - // be made in gui/wxmain.cc, MyFrame::editFloppyConfig. - bx_options.floppya.Opath, - bx_options.floppya.Otype, - bx_options.floppya.Ostatus, - NULL - }; - menu = new bx_list_c (BXP_FLOPPYA, "Floppy Disk 0", "All options for first floppy disk", floppya_init_list); - menu->get_options ()->set (menu->SERIES_ASK); - bx_options.floppya.Opath->set_handler (bx_param_string_handler); - bx_options.floppya.Opath->set ("none"); - bx_options.floppya.Otype->set_handler (bx_param_handler); - bx_options.floppya.Ostatus->set_handler (bx_param_handler); - - bx_options.floppyb.Opath = new bx_param_filename_c (BXP_FLOPPYB_PATH, - "floppyb:path", - "Pathname of second floppy image file or device.", - "", BX_PATHNAME_LEN); - bx_options.floppyb.Opath->set_ask_format ("Enter new filename, or 'none' for no disk: [%s] "); - bx_options.floppyb.Opath->set_label ("Second floppy image/device"); - bx_options.floppyb.Odevtype = new bx_param_enum_c (BXP_FLOPPYB_DEVTYPE, - "floppyb:devtype", - "Type of floppy drive", - floppy_type_names, - BX_FLOPPY_NONE, - BX_FLOPPY_NONE); - bx_options.floppyb.Otype = new bx_param_enum_c (BXP_FLOPPYB_TYPE, - "floppyb:type", - "Type of floppy disk", - floppy_type_names, - BX_FLOPPY_NONE, - BX_FLOPPY_NONE); - bx_options.floppyb.Otype->set_ask_format ("What type of floppy disk? [%s] "); - bx_options.floppyb.Ostatus = new bx_param_enum_c (BXP_FLOPPYB_STATUS, - "Is floppyb inserted", - "Inserted or ejected", - floppy_status_names, - BX_INSERTED, - BX_EJECTED); - bx_options.floppyb.Ostatus->set_ask_format ("Is the floppy inserted or ejected? [%s] "); - bx_options.floppyb.Opath->set_format ("%s"); - bx_options.floppyb.Otype->set_format ("size=%s"); - bx_options.floppyb.Ostatus->set_format ("%s"); - bx_param_c *floppyb_init_list[] = { - bx_options.floppyb.Opath, - bx_options.floppyb.Otype, - bx_options.floppyb.Ostatus, - NULL - }; - menu = new bx_list_c (BXP_FLOPPYB, "Floppy Disk 1", "All options for second floppy disk", floppyb_init_list); - menu->get_options ()->set (menu->SERIES_ASK); - bx_options.floppyb.Opath->set_handler (bx_param_string_handler); - bx_options.floppyb.Opath->set ("none"); - bx_options.floppyb.Otype->set_handler (bx_param_handler); - bx_options.floppyb.Ostatus->set_handler (bx_param_handler); - - // disk options - - // FIXME use descr and name - char *s_atachannel[] = { - "ATA channel 0", - "ATA channel 1", - "ATA channel 2", - "ATA channel 3", - }; - char *s_atadevice[4][2] = { - { "First HD/CD on channel 0", - "Second HD/CD on channel 0" }, - { "First HD/CD on channel 1", - "Second HD/CD on channel 1" }, - { "First HD/CD on channel 2", - "Second HD/CD on channel 2" }, - { "First HD/CD on channel 3", - "Second HD/CD on channel 3" } - }; - Bit16u ata_default_ioaddr1[BX_MAX_ATA_CHANNEL] = { - 0x1f0, 0x170, 0x1e8, 0x168 - }; - Bit16u ata_default_ioaddr2[BX_MAX_ATA_CHANNEL] = { - 0x3f0, 0x370, 0x3e0, 0x360 - }; - Bit8u ata_default_irq[BX_MAX_ATA_CHANNEL] = { - 14, 15, 11, 9 - }; - - bx_list_c *ata[BX_MAX_ATA_CHANNEL]; - bx_list_c *ata_menu[BX_MAX_ATA_CHANNEL]; - - Bit8u channel; - for (channel=0; channelget_options ()->set (bx_list_c::SERIES_ASK); - - ata[channel]->add (bx_options.ata[channel].Opresent = new bx_param_bool_c ((bx_id)(BXP_ATAx_PRESENT(channel)), - "ata:present", - "Controls whether ata channel is installed or not", - 0)); - - ata[channel]->add (bx_options.ata[channel].Oioaddr1 = new bx_param_num_c ((bx_id)(BXP_ATAx_IOADDR1(channel)), - "ata:ioaddr1", - "IO adress of ata command block", - 0, 0xffff, - ata_default_ioaddr1[channel])); - - ata[channel]->add (bx_options.ata[channel].Oioaddr2 = new bx_param_num_c ((bx_id)(BXP_ATAx_IOADDR2(channel)), - "ata:ioaddr2", - "IO adress of ata control block", - 0, 0xffff, - ata_default_ioaddr2[channel])); - - ata[channel]->add (bx_options.ata[channel].Oirq = new bx_param_num_c ((bx_id)(BXP_ATAx_IRQ(channel)), - "ata:irq", - "IRQ used by this ata channel", - 0, 15, - ata_default_irq[channel])); - - // all items in the ata[channel] menu depend on the present flag. - // The menu list is complete, but a few dependent_list items will - // be added later. Use clone() to make a copy of the dependent_list - // so that it can be changed without affecting the menu. - bx_options.ata[channel].Opresent->set_dependent_list ( - ata[channel]->clone()); - - for (Bit8u slave=0; slave<2; slave++) { - - menu = bx_options.atadevice[channel][slave].Omenu = new bx_list_c ((bx_id)(BXP_ATAx_DEVICE(channel,slave)), - s_atadevice[channel][slave], - s_atadevice[channel][slave], - BXP_PARAMS_PER_ATA_DEVICE + 1 ); - menu->get_options ()->set (menu->SERIES_ASK); - - menu->add (bx_options.atadevice[channel][slave].Opresent = new bx_param_bool_c ((bx_id)(BXP_ATAx_DEVICE_PRESENT(channel,slave)), - "ata-device:present", - "Controls whether ata device is installed or not", - 0)); - - menu->add (bx_options.atadevice[channel][slave].Otype = new bx_param_enum_c ((bx_id)(BXP_ATAx_DEVICE_TYPE(channel,slave)), - "ata-device:type", - "Type of ATA device (disk or cdrom)", - atadevice_type_names, - BX_ATA_DEVICE_DISK, - BX_ATA_DEVICE_DISK)); - - menu->add (bx_options.atadevice[channel][slave].Opath = new bx_param_filename_c ((bx_id)(BXP_ATAx_DEVICE_PATH(channel,slave)), - "ata-device:path", - "Pathname of the image or physical device (cdrom only)", - "", BX_PATHNAME_LEN)); - - menu->add (bx_options.atadevice[channel][slave].Omode = new bx_param_enum_c ((bx_id)(BXP_ATAx_DEVICE_MODE(channel,slave)), - "ata-device:mode", - "Mode of the ATA harddisk", - atadevice_mode_names, - BX_ATA_MODE_FLAT, - BX_ATA_MODE_FLAT)); - - menu->add (bx_options.atadevice[channel][slave].Ostatus = new bx_param_enum_c ((bx_id)(BXP_ATAx_DEVICE_STATUS(channel,slave)), - "ata-device:status", - "CD-ROM media status (inserted / ejected)", - atadevice_status_names, - BX_INSERTED, - BX_EJECTED)); - - menu->add (bx_options.atadevice[channel][slave].Ojournal = new bx_param_filename_c ((bx_id)(BXP_ATAx_DEVICE_JOURNAL(channel,slave)), - "ata-device:journal", - "Pathname of the journal file", - "", BX_PATHNAME_LEN)); - - menu->add (bx_options.atadevice[channel][slave].Ocylinders = new bx_param_num_c ((bx_id)(BXP_ATAx_DEVICE_CYLINDERS(channel,slave)), - "ata-device:cylinders", - "Number of cylinders", - 0, 65535, - 0)); - menu->add (bx_options.atadevice[channel][slave].Oheads = new bx_param_num_c ((bx_id)(BXP_ATAx_DEVICE_HEADS(channel,slave)), - "ata-device:heads", - "Number of heads", - 0, 65535, - 0)); - menu->add (bx_options.atadevice[channel][slave].Ospt = new bx_param_num_c ((bx_id)(BXP_ATAx_DEVICE_SPT(channel,slave)), - "ata-device:spt", - "Number of sectors per track", - 0, 65535, - 0)); - - menu->add (bx_options.atadevice[channel][slave].Omodel = new bx_param_string_c ((bx_id)(BXP_ATAx_DEVICE_MODEL(channel,slave)), - "ata-device:model", - "String returned by the 'identify device' command", - "Generic 1234", 40)); - - menu->add (bx_options.atadevice[channel][slave].Obiosdetect = new bx_param_enum_c ((bx_id)(BXP_ATAx_DEVICE_BIOSDETECT(channel,slave)), - "ata-device:biosdetect", - "Type of bios detection", - atadevice_biosdetect_names, - BX_ATA_BIOSDETECT_AUTO, - BX_ATA_BIOSDETECT_NONE)); - - menu->add (bx_options.atadevice[channel][slave].Otranslation = new bx_param_enum_c ((bx_id)(BXP_ATAx_DEVICE_TRANSLATION(channel,slave)), - "How the ata-disk translation is done by the bios", - "Type of translation", - atadevice_translation_names, - BX_ATA_TRANSLATION_AUTO, - BX_ATA_TRANSLATION_NONE)); - - bx_options.atadevice[channel][slave].Opresent->set_dependent_list ( - menu->clone ()); - // the menu and all items on it depend on the Opresent flag - bx_options.atadevice[channel][slave].Opresent->get_dependent_list()->add(menu); - // the present flag depends on the ATA channel's present flag - bx_options.ata[channel].Opresent->get_dependent_list()->add ( - bx_options.atadevice[channel][slave].Opresent); - } - - // set up top level menu for ATA[i] controller configuration. This list - // controls what will appear on the ATA configure dialog. It now - // requests the USE_TAB_WINDOW display, which is implemented in wx. - char buffer[32]; - sprintf (buffer, "Configure ATA%d", channel); - ata_menu[channel] = new bx_list_c ((bx_id)(BXP_ATAx_MENU(channel)), strdup(buffer), "", 4); - ata_menu[channel]->add (ata[channel]); - ata_menu[channel]->add (bx_options.atadevice[channel][0].Omenu); - ata_menu[channel]->add (bx_options.atadevice[channel][1].Omenu); - ata_menu[channel]->get_options()->set (bx_list_c::USE_TAB_WINDOW); - } - - // Enable first ata interface by default, disable the others. - bx_options.ata[0].Opresent->set_initial_val(1); - - // now that the dependence relationships are established, call set() on - // the ata device present params to set all enables correctly. - for (i=0; iset (i==0); - - for (channel=0; channelset_ask_format ("Channel is enabled: [%s] "); - bx_options.ata[channel].Oioaddr1->set_ask_format ("Enter new ioaddr1: [0x%x] "); - bx_options.ata[channel].Oioaddr2->set_ask_format ("Enter new ioaddr2: [0x%x] "); - bx_options.ata[channel].Oirq->set_ask_format ("Enter new IRQ: [%d] "); -#if BX_WITH_WX - bx_options.ata[channel].Opresent->set_label ("Enable this channel?"); - bx_options.ata[channel].Oioaddr1->set_label ("I/O Address 1:"); - bx_options.ata[channel].Oioaddr2->set_label ("I/O Address 2:"); - bx_options.ata[channel].Oirq->set_label ("IRQ:"); - bx_options.ata[channel].Oirq->set_options (bx_param_num_c::USE_SPIN_CONTROL); -#else - bx_options.ata[channel].Opresent->set_format ("enabled: %s"); - bx_options.ata[channel].Oioaddr1->set_format ("ioaddr1: 0x%x"); - bx_options.ata[channel].Oioaddr2->set_format ("ioaddr2: 0x%x"); - bx_options.ata[channel].Oirq->set_format ("irq: %d"); -#endif - bx_options.ata[channel].Oioaddr1->set_base (16); - bx_options.ata[channel].Oioaddr2->set_base (16); - - for (Bit8u slave=0; slave<2; slave++) { - - bx_options.atadevice[channel][slave].Opresent->set_ask_format ( - "Device is enabled: [%s] "); - bx_options.atadevice[channel][slave].Otype->set_ask_format ( - "Enter type of ATA device, disk or cdrom: [%s] "); - bx_options.atadevice[channel][slave].Omode->set_ask_format ( - "Enter mode of ATA device, (flat, concat, etc.): [%s] "); - bx_options.atadevice[channel][slave].Opath->set_ask_format ( - "Enter new filename: [%s] "); - bx_options.atadevice[channel][slave].Ocylinders->set_ask_format ( - "Enter number of cylinders: [%d] "); - bx_options.atadevice[channel][slave].Oheads->set_ask_format ( - "Enter number of heads: [%d] "); - bx_options.atadevice[channel][slave].Ospt->set_ask_format ( - "Enter number of sectors per track: [%d] "); - bx_options.atadevice[channel][slave].Ostatus->set_ask_format ( - "Is the device inserted or ejected? [%s] "); - bx_options.atadevice[channel][slave].Omodel->set_ask_format ( - "Enter new model name: [%s]"); - bx_options.atadevice[channel][slave].Otranslation->set_ask_format ( - "Enter translation type: [%s]"); - bx_options.atadevice[channel][slave].Obiosdetect->set_ask_format ( - "Enter bios detection type: [%s]"); - bx_options.atadevice[channel][slave].Ojournal->set_ask_format ( - "Enter path of journal file: [%s]"); - -#if BX_WITH_WX - bx_options.atadevice[channel][slave].Opresent->set_label ( - "Enable this device?"); - bx_options.atadevice[channel][slave].Otype->set_label ( - "Type of ATA device:"); - bx_options.atadevice[channel][slave].Omode->set_label ( - "Type of disk image:"); - bx_options.atadevice[channel][slave].Opath->set_label ( - "Path or physical device name:"); - bx_options.atadevice[channel][slave].Ocylinders->set_label ( - "Cylinders:"); - bx_options.atadevice[channel][slave].Oheads->set_label ( - "Heads:"); - bx_options.atadevice[channel][slave].Ospt->set_label ( - "Sectors per track:"); - bx_options.atadevice[channel][slave].Ostatus->set_label ( - "Inserted?"); - bx_options.atadevice[channel][slave].Omodel->set_label ( - "Model name:"); - bx_options.atadevice[channel][slave].Otranslation->set_label ( - "Translation type:"); - bx_options.atadevice[channel][slave].Obiosdetect->set_label ( - "BIOS Detection:"); - bx_options.atadevice[channel][slave].Ojournal->set_label ( - "Path of journal file:"); -#else - bx_options.atadevice[channel][slave].Opresent->set_format ("enabled: %s"); - bx_options.atadevice[channel][slave].Otype->set_format ("type %s"); - bx_options.atadevice[channel][slave].Omode->set_format ("mode %s"); - bx_options.atadevice[channel][slave].Opath->set_format ("path '%s'"); - bx_options.atadevice[channel][slave].Ocylinders->set_format ("%d cylinders"); - bx_options.atadevice[channel][slave].Oheads->set_format ("%d heads"); - bx_options.atadevice[channel][slave].Ospt->set_format ("%d sectors/track"); - bx_options.atadevice[channel][slave].Ostatus->set_format ("%s"); - bx_options.atadevice[channel][slave].Omodel->set_format ("model '%s'"); - bx_options.atadevice[channel][slave].Otranslation->set_format ("translation '%s'"); - bx_options.atadevice[channel][slave].Obiosdetect->set_format ("biosdetect '%s'"); - bx_options.atadevice[channel][slave].Ojournal->set_format ("journal is '%s'"); -#endif - - bx_options.atadevice[channel][slave].Otype->set_handler (bx_param_handler); - bx_options.atadevice[channel][slave].Omode->set_handler (bx_param_handler); - bx_options.atadevice[channel][slave].Ostatus->set_handler (bx_param_handler); - bx_options.atadevice[channel][slave].Opath->set_handler (bx_param_string_handler); - - // Set the enable_hanlders - bx_options.atadevice[channel][slave].Ojournal->set_enable_handler (bx_param_enable_handler); - bx_options.atadevice[channel][slave].Ostatus->set_enable_handler (bx_param_enable_handler); - - } - } - - bx_options.OnewHardDriveSupport = new bx_param_bool_c (BXP_NEWHARDDRIVESUPPORT, - "New hard drive support", - "Enables new features found on newer hard drives.", - 1); - - bx_options.Obootdrive = new bx_param_enum_c (BXP_BOOTDRIVE, - "bootdrive", - "Boot A, C or CD", - floppy_bootdisk_names, - BX_BOOT_FLOPPYA, - BX_BOOT_FLOPPYA); - bx_options.Obootdrive->set_format ("Boot from: %s drive"); - bx_options.Obootdrive->set_ask_format ("Boot from floppy drive, hard drive or cdrom ? [%s] "); - - bx_options.OfloppySigCheck = new bx_param_bool_c (BXP_FLOPPYSIGCHECK, - "Skip Floppy Boot Signature Check", - "Skips check for the 0xaa55 signature on floppy boot device.", - 0); - - // disk menu - bx_param_c *disk_menu_init_list[] = { - SIM->get_param (BXP_FLOPPYA), - SIM->get_param (BXP_FLOPPYB), - SIM->get_param (BXP_ATA0), - SIM->get_param (BXP_ATA0_MASTER), - SIM->get_param (BXP_ATA0_SLAVE), -#if BX_MAX_ATA_CHANNEL>1 - SIM->get_param (BXP_ATA1), - SIM->get_param (BXP_ATA1_MASTER), - SIM->get_param (BXP_ATA1_SLAVE), -#endif -#if BX_MAX_ATA_CHANNEL>2 - SIM->get_param (BXP_ATA2), - SIM->get_param (BXP_ATA2_MASTER), - SIM->get_param (BXP_ATA2_SLAVE), -#endif -#if BX_MAX_ATA_CHANNEL>3 - SIM->get_param (BXP_ATA3), - SIM->get_param (BXP_ATA3_MASTER), - SIM->get_param (BXP_ATA3_SLAVE), -#endif - SIM->get_param (BXP_NEWHARDDRIVESUPPORT), - SIM->get_param (BXP_BOOTDRIVE), - SIM->get_param (BXP_FLOPPYSIGCHECK), - NULL - }; - menu = new bx_list_c (BXP_MENU_DISK, "Bochs Disk Options", "diskmenu", disk_menu_init_list); - menu->get_options ()->set (menu->SHOW_PARENT); - - // memory options menu - bx_options.memory.Osize = new bx_param_num_c (BXP_MEM_SIZE, - "megs", - "Amount of RAM in megabytes", - 1, BX_MAX_BIT32U, - BX_DEFAULT_MEM_MEGS); - bx_options.memory.Osize->set_ask_format ("Enter memory size (MB): [%d] "); -#if BX_WITH_WX - bx_options.memory.Osize->set_label ("Memory size (megabytes)"); - bx_options.memory.Osize->set_options (bx_param_num_c::USE_SPIN_CONTROL); -#else - bx_options.memory.Osize->set_format ("Memory size in megabytes: %d"); -#endif - - // initialize serial and parallel port options -#define PAR_SER_INIT_LIST_MAX \ - ((BXP_PARAMS_PER_PARALLEL_PORT * BX_N_PARALLEL_PORTS) \ - + (BXP_PARAMS_PER_SERIAL_PORT * BX_N_SERIAL_PORTS) \ - + (BXP_PARAMS_PER_USB_HUB * BX_N_USB_HUBS)) - bx_param_c *par_ser_init_list[1+PAR_SER_INIT_LIST_MAX]; - bx_param_c **par_ser_ptr = &par_ser_init_list[0]; - - // parallel ports - for (i=0; iadd (bx_options.par[i].Ooutfile); - bx_options.par[i].Oenabled->set_dependent_list (deplist); - // add to menu - *par_ser_ptr++ = bx_options.par[i].Oenabled; - *par_ser_ptr++ = bx_options.par[i].Ooutfile; - } - - // serial ports - for (i=0; iadd (bx_options.com[i].Odev); - bx_options.com[i].Oenabled->set_dependent_list (deplist); - // add to menu - *par_ser_ptr++ = bx_options.com[i].Oenabled; - *par_ser_ptr++ = bx_options.com[i].Odev; - } - - // usb hubs - for (i=0; iadd (bx_options.usb[i].Oioaddr); - deplist->add (bx_options.usb[i].Oirq); - bx_options.usb[i].Oenabled->set_dependent_list (deplist); - // add to menu - *par_ser_ptr++ = bx_options.usb[i].Oenabled; - *par_ser_ptr++ = bx_options.usb[i].Oioaddr; - *par_ser_ptr++ = bx_options.usb[i].Oirq; - - bx_options.usb[i].Oioaddr->set_ask_format ("Enter new ioaddr: [0x%x] "); - bx_options.usb[i].Oioaddr->set_label ("I/O Address"); - bx_options.usb[i].Oioaddr->set_base (16); - bx_options.usb[i].Oenabled->set_label (strdup(label)); - bx_options.usb[i].Oirq->set_label ("USB IRQ"); - bx_options.usb[i].Oirq->set_options (bx_param_num_c::USE_SPIN_CONTROL); - } - // add final NULL at the end, and build the menu - *par_ser_ptr = NULL; - menu = new bx_list_c (BXP_MENU_SERIAL_PARALLEL, - "Serial and Parallel Port Options", - "serial_parallel_menu", - par_ser_init_list); - menu->get_options ()->set (menu->SHOW_PARENT); - - bx_options.rom.Opath = new bx_param_filename_c (BXP_ROM_PATH, - "romimage", - "Pathname of ROM image to load", - "", BX_PATHNAME_LEN); - bx_options.rom.Opath->set_format ("Name of ROM BIOS image: %s"); - bx_options.rom.Oaddress = new bx_param_num_c (BXP_ROM_ADDRESS, - "romaddr", - "The address at which the ROM image should be loaded", - 0, BX_MAX_BIT32U, - 0xf0000); - bx_options.rom.Oaddress->set_base (16); -#if BX_WITH_WX - bx_options.rom.Opath->set_label ("ROM BIOS image"); - bx_options.rom.Oaddress->set_label ("ROM BIOS address"); -#else - bx_options.rom.Oaddress->set_format ("ROM BIOS address: 0x%05x"); -#endif - - bx_options.optrom[0].Opath = new bx_param_filename_c (BXP_OPTROM1_PATH, - "optional romimage #1", - "Pathname of optional ROM image #1 to load", - "", BX_PATHNAME_LEN); - bx_options.optrom[0].Opath->set_format ("Name of optional ROM image #1 : %s"); - bx_options.optrom[0].Oaddress = new bx_param_num_c (BXP_OPTROM1_ADDRESS, - "optional romaddr #1", - "The address at which the optional ROM image #1 should be loaded", - 0, BX_MAX_BIT32U, - 0); - bx_options.optrom[0].Oaddress->set_base (16); -#if BX_WITH_WX - bx_options.optrom[0].Opath->set_label ("Optional ROM image #1"); - bx_options.optrom[0].Oaddress->set_label ("Address"); -#else - bx_options.optrom[0].Oaddress->set_format ("optional ROM #1 address: 0x%05x"); -#endif - - bx_options.optrom[1].Opath = new bx_param_filename_c (BXP_OPTROM2_PATH, - "optional romimage #2", - "Pathname of optional ROM image #2 to load", - "", BX_PATHNAME_LEN); - bx_options.optrom[1].Opath->set_format ("Name of optional ROM image #2 : %s"); - bx_options.optrom[1].Oaddress = new bx_param_num_c (BXP_OPTROM2_ADDRESS, - "optional romaddr #2", - "The address at which the optional ROM image #2 should be loaded", - 0, BX_MAX_BIT32U, - 0); - bx_options.optrom[1].Oaddress->set_base (16); -#if BX_WITH_WX - bx_options.optrom[1].Opath->set_label ("Optional ROM image #2"); - bx_options.optrom[1].Oaddress->set_label ("Address"); -#else - bx_options.optrom[1].Oaddress->set_format ("optional ROM #2 address: 0x%05x"); -#endif - - bx_options.optrom[2].Opath = new bx_param_filename_c (BXP_OPTROM3_PATH, - "optional romimage #3", - "Pathname of optional ROM image #3 to load", - "", BX_PATHNAME_LEN); - bx_options.optrom[2].Opath->set_format ("Name of optional ROM image #3 : %s"); - bx_options.optrom[2].Oaddress = new bx_param_num_c (BXP_OPTROM3_ADDRESS, - "optional romaddr #3", - "The address at which the optional ROM image #3 should be loaded", - 0, BX_MAX_BIT32U, - 0); - bx_options.optrom[2].Oaddress->set_base (16); -#if BX_WITH_WX - bx_options.optrom[2].Opath->set_label ("Optional ROM image #3"); - bx_options.optrom[2].Oaddress->set_label ("Address"); -#else - bx_options.optrom[2].Oaddress->set_format ("optional ROM #3 address: 0x%05x"); -#endif - - bx_options.optrom[3].Opath = new bx_param_filename_c (BXP_OPTROM4_PATH, - "optional romimage #4", - "Pathname of optional ROM image #4 to load", - "", BX_PATHNAME_LEN); - bx_options.optrom[3].Opath->set_format ("Name of optional ROM image #4 : %s"); - bx_options.optrom[3].Oaddress = new bx_param_num_c (BXP_OPTROM4_ADDRESS, - "optional romaddr #4", - "The address at which the optional ROM image #4 should be loaded", - 0, BX_MAX_BIT32U, - 0); - bx_options.optrom[3].Oaddress->set_base (16); -#if BX_WITH_WX - bx_options.optrom[3].Opath->set_label ("Optional ROM image #4"); - bx_options.optrom[3].Oaddress->set_label ("Address"); -#else - bx_options.optrom[3].Oaddress->set_format ("optional ROM #4 address: 0x%05x"); -#endif - - bx_options.vgarom.Opath = new bx_param_filename_c (BXP_VGA_ROM_PATH, - "vgaromimage", - "Pathname of VGA ROM image to load", - "", BX_PATHNAME_LEN); - bx_options.vgarom.Opath->set_format ("Name of VGA BIOS image: %s"); -#if BX_WITH_WX - bx_options.vgarom.Opath->set_label ("VGA BIOS image"); -#endif - bx_param_c *memory_init_list[] = { - bx_options.memory.Osize, - bx_options.vgarom.Opath, - bx_options.rom.Opath, - bx_options.rom.Oaddress, - bx_options.optrom[0].Opath, - bx_options.optrom[0].Oaddress, - bx_options.optrom[1].Opath, - bx_options.optrom[1].Oaddress, - bx_options.optrom[2].Opath, - bx_options.optrom[2].Oaddress, - bx_options.optrom[3].Opath, - bx_options.optrom[3].Oaddress, - NULL - }; - menu = new bx_list_c (BXP_MENU_MEMORY, "Bochs Memory Options", "memmenu", memory_init_list); - menu->get_options ()->set (menu->SHOW_PARENT); - - // interface - bx_options.Ovga_update_interval = new bx_param_num_c (BXP_VGA_UPDATE_INTERVAL, - "VGA Update Interval", - "Number of microseconds between VGA updates", - 1, BX_MAX_BIT32U, - 30000); - bx_options.Ovga_update_interval->set_handler (bx_param_handler); - bx_options.Ovga_update_interval->set_runtime_param (1); - bx_options.Ovga_update_interval->set_ask_format ("Type a new value for VGA update interval: [%d] "); - bx_options.Omouse_enabled = new bx_param_bool_c (BXP_MOUSE_ENABLED, - "Enable the mouse", - "Controls whether the mouse sends events to the guest. The hardware emulation is always enabled.", - 0); - bx_options.Omouse_enabled->set_handler (bx_param_handler); - bx_options.Omouse_enabled->set_runtime_param (1); - bx_options.Oips = new bx_param_num_c (BXP_IPS, - "Emulated instructions per second (IPS)", - "Emulated instructions per second, used to calibrate bochs emulated time with wall clock time.", - 1, BX_MAX_BIT32U, - 500000); - bx_options.Otext_snapshot_check = new bx_param_bool_c (BXP_TEXT_SNAPSHOT_CHECK, - "Enable panic for use in bochs testing", - "Enable panic when text on screen matches snapchk.txt.\nUseful for regression testing.\nIn win32, turns off CR/LF in snapshots and cuts.", - 0); - bx_options.Oprivate_colormap = new bx_param_bool_c (BXP_PRIVATE_COLORMAP, - "Use a private colormap", - "Request that the GUI create and use it's own non-shared colormap. This colormap will be used when in the bochs window. If not enabled, a shared colormap scheme may be used. Not implemented on all GUI's.", - 0); -#if BX_WITH_AMIGAOS - bx_options.Ofullscreen = new bx_param_bool_c (BXP_FULLSCREEN, - "Use full screen mode", - "When enabled, bochs occupies the whole screen instead of just a window.", - 0); - bx_options.Oscreenmode = new bx_param_string_c (BXP_SCREENMODE, - "Screen mode name", - "Screen mode name", - "", BX_PATHNAME_LEN); - bx_options.Oscreenmode->set_handler (bx_param_string_handler); -#endif - static char *config_interface_list[] = { - "textconfig", -#if BX_WITH_WX - "wx", -#endif - NULL - }; - bx_options.Osel_config = new bx_param_enum_c ( - BXP_SEL_CONFIG_INTERFACE, - "Configuration interface", - "Select configuration interface", - config_interface_list, - 0, - 0); - bx_options.Osel_config->set_by_name (BX_DEFAULT_CONFIG_INTERFACE); - bx_options.Osel_config->set_ask_format ("Choose which configuration interface to use: [%s] "); - // this is a list of gui libraries that are known to be available at - // compile time. The one that is listed first will be the default, - // which is used unless the user overrides it on the command line or - // in a configuration file. - static char *display_library_list[] = { -#if BX_WITH_X11 - "x", -#endif -#if BX_WITH_WIN32 - "win32", -#endif -#if BX_WITH_CARBON - "carbon", -#endif -#if BX_WITH_BEOS - "beos", -#endif -#if BX_WITH_MACOS - "macos", -#endif -#if BX_WITH_AMIGAOS - "amigaos", -#endif -#if BX_WITH_SDL - "sdl", -#endif -#if BX_WITH_SVGA - "svga", -#endif -#if BX_WITH_TERM - "term", -#endif -#if BX_WITH_RFB - "rfb", -#endif -#if BX_WITH_WX - "wx", -#endif -#if BX_WITH_NOGUI - "nogui", -#endif - NULL - }; - bx_options.Osel_displaylib = new bx_param_enum_c (BXP_SEL_DISPLAY_LIBRARY, - "VGA Display Library", - "Select VGA Display Library", - display_library_list, - 0, - 0); - bx_options.Osel_displaylib->set_by_name (BX_DEFAULT_DISPLAY_LIBRARY); - bx_options.Osel_displaylib->set_ask_format ("Choose which library to use for the Bochs display: [%s] "); - bx_param_c *interface_init_list[] = { - bx_options.Osel_config, - bx_options.Osel_displaylib, - bx_options.Ovga_update_interval, - bx_options.Omouse_enabled, - bx_options.Oips, - bx_options.Oprivate_colormap, -#if BX_WITH_AMIGAOS - bx_options.Ofullscreen, - bx_options.Oscreenmode, -#endif - NULL - }; - menu = new bx_list_c (BXP_MENU_INTERFACE, "Bochs Interface Menu", "intfmenu", interface_init_list); - menu->get_options ()->set (menu->SHOW_PARENT); - - // NE2K options - bx_options.ne2k.Opresent = new bx_param_bool_c (BXP_NE2K_PRESENT, - "Enable NE2K NIC emulation", - "Enables the NE2K NIC emulation", - 0); - bx_options.ne2k.Oioaddr = new bx_param_num_c (BXP_NE2K_IOADDR, - "NE2K I/O Address", - "I/O base address of the emulated NE2K device", - 0, 0xffff, - 0x240); - bx_options.ne2k.Oioaddr->set_base (16); - bx_options.ne2k.Oirq = new bx_param_num_c (BXP_NE2K_IRQ, - "NE2K Interrupt", - "IRQ used by the NE2K device", - 0, 15, - 9); - bx_options.ne2k.Oirq->set_options (bx_param_num_c::USE_SPIN_CONTROL); - bx_options.ne2k.Omacaddr = new bx_param_string_c (BXP_NE2K_MACADDR, - "MAC Address", - "MAC address of the NE2K device. Don't use an address of a machine on your net.", - "\xfe\xfd\xde\xad\xbe\xef", 6); - bx_options.ne2k.Omacaddr->get_options ()->set (bx_options.ne2k.Omacaddr->RAW_BYTES); - bx_options.ne2k.Omacaddr->set_separator (':'); - static char *eth_module_list[] = { - "null", -#if defined(ETH_LINUX) - "linux", -#endif -#if HAVE_ETHERTAP - "tap", -#endif -#if HAVE_TUNTAP - "tuntap", -#endif -#if defined(ETH_WIN32) - "win32", -#endif -#if defined(ETH_FBSD) - "fbsd", -#endif -#ifdef ETH_ARPBACK - "arpback", -#endif - NULL - }; - bx_options.ne2k.Oethmod = new bx_param_enum_c (BXP_NE2K_ETHMOD, - "Ethernet module", - "Module used for the connection to the real net.", - eth_module_list, - 0, - 0); - bx_options.ne2k.Oethmod->set_by_name ("null"); - bx_options.ne2k.Oethdev = new bx_param_string_c (BXP_NE2K_ETHDEV, - "Ethernet device", - "Device used for the connection to the real net. This is only valid if an ethernet module other than 'null' is used.", - "xl0", BX_PATHNAME_LEN); - bx_options.ne2k.Oscript = new bx_param_string_c (BXP_NE2K_SCRIPT, - "Device configuration script", - "Name of the script that is executed after Bochs initializes the network interface (optional).", - "none", BX_PATHNAME_LEN); -#if !BX_WITH_WX - bx_options.ne2k.Oscript->set_ask_format ("Enter new script name, or 'none': [%s] "); -#endif - bx_param_c *ne2k_init_list[] = { - bx_options.ne2k.Opresent, - bx_options.ne2k.Oioaddr, - bx_options.ne2k.Oirq, - bx_options.ne2k.Omacaddr, - bx_options.ne2k.Oethmod, - bx_options.ne2k.Oethdev, - bx_options.ne2k.Oscript, - NULL - }; - menu = new bx_list_c (BXP_NE2K, "NE2K Configuration", "", ne2k_init_list); - menu->get_options ()->set (menu->SHOW_PARENT); - bx_param_c **ne2k_dependent_list = &ne2k_init_list[1]; - bx_options.ne2k.Opresent->set_dependent_list ( - new bx_list_c (BXP_NULL, "", "", ne2k_dependent_list)); - bx_options.ne2k.Opresent->set_handler (bx_param_handler); - bx_options.ne2k.Opresent->set (0); - - // SB16 options - bx_options.sb16.Opresent = new bx_param_bool_c (BXP_SB16_PRESENT, - "Enable SB16 emulation", - "Enables the SB16 emulation", - 0); - bx_options.sb16.Omidifile = new bx_param_filename_c (BXP_SB16_MIDIFILE, - "MIDI file", - "The filename is where the MIDI data is sent. This can be device or just a file.", - "", BX_PATHNAME_LEN); - bx_options.sb16.Owavefile = new bx_param_filename_c (BXP_SB16_WAVEFILE, - "Wave file", - "This is the device/file where the wave output is stored", - "", BX_PATHNAME_LEN); - bx_options.sb16.Ologfile = new bx_param_filename_c (BXP_SB16_LOGFILE, - "Log file", - "The file to write the SB16 emulator messages to.", - "", BX_PATHNAME_LEN); - bx_options.sb16.Omidimode = new bx_param_num_c (BXP_SB16_MIDIMODE, - "Midi mode", - "Controls the MIDI output format.", - 0, 3, - 0); - bx_options.sb16.Owavemode = new bx_param_num_c (BXP_SB16_WAVEMODE, - "Wave mode", - "Controls the wave output format.", - 0, 3, - 0); - bx_options.sb16.Ologlevel = new bx_param_num_c (BXP_SB16_LOGLEVEL, - "Log mode", - "Controls how verbose the SB16 emulation is (0 = no log, 5 = all errors and infos).", - 0, 5, - 0); - bx_options.sb16.Odmatimer = new bx_param_num_c (BXP_SB16_DMATIMER, - "DMA timer", - "Microseconds per second for a DMA cycle.", - 0, BX_MAX_BIT32U, - 0); - -#if BX_WITH_WX - bx_options.sb16.Omidimode->set_options (bx_param_num_c::USE_SPIN_CONTROL); - bx_options.sb16.Owavemode->set_options (bx_param_num_c::USE_SPIN_CONTROL); - bx_options.sb16.Ologlevel->set_options (bx_param_num_c::USE_SPIN_CONTROL); -#endif - bx_param_c *sb16_init_list[] = { - bx_options.sb16.Opresent, - bx_options.sb16.Omidimode, - bx_options.sb16.Omidifile, - bx_options.sb16.Owavemode, - bx_options.sb16.Owavefile, - bx_options.sb16.Ologlevel, - bx_options.sb16.Ologfile, - bx_options.sb16.Odmatimer, - NULL - }; - menu = new bx_list_c (BXP_SB16, "SB16 Configuration", "", sb16_init_list); - menu->get_options ()->set (menu->SHOW_PARENT); - // sb16_dependent_list is a null-terminated list including all the - // sb16 fields except for the "present" field. These will all be enabled/ - // disabled according to the value of the present field. - bx_param_c **sb16_dependent_list = &sb16_init_list[1]; - bx_options.sb16.Opresent->set_dependent_list ( - new bx_list_c (BXP_NULL, "", "", sb16_dependent_list)); - - bx_options.log.Ofilename = new bx_param_filename_c (BXP_LOG_FILENAME, - "Log filename", - "Pathname of bochs log file", - "-", BX_PATHNAME_LEN); - bx_options.log.Ofilename->set_ask_format ("Enter log filename: [%s] "); - - bx_options.log.Oprefix = new bx_param_string_c (BXP_LOG_PREFIX, - "Log output prefix", - "Prefix prepended to log output", - "%t%e%d", BX_PATHNAME_LEN); - bx_options.log.Oprefix->set_ask_format ("Enter log prefix: [%s] "); - - bx_options.log.Odebugger_filename = new bx_param_filename_c (BXP_DEBUGGER_LOG_FILENAME, - "Debugger Log filename", - "Pathname of debugger log file", - "-", BX_PATHNAME_LEN); - bx_options.log.Odebugger_filename->set_ask_format ("Enter debugger log filename: [%s] "); - - // loader - bx_options.load32bitOSImage.OwhichOS = new bx_param_enum_c (BXP_LOAD32BITOS_WHICH, - "Which operating system?", - "Which OS to boot", - loader_os_names, -#ifdef BX_USE_VMX - Load32bitOSLinux, -#else - Load32bitOSNone, -#endif - Load32bitOSNone); - bx_options.load32bitOSImage.Opath = new bx_param_filename_c (BXP_LOAD32BITOS_PATH, - "Pathname of OS to load", - "Pathname of the 32-bit OS to load", - "", BX_PATHNAME_LEN); - bx_options.load32bitOSImage.Oiolog = new bx_param_filename_c (BXP_LOAD32BITOS_IOLOG, - "Pathname of I/O log file", - "I/O logfile used for initializing the hardware", - "", BX_PATHNAME_LEN); - bx_options.load32bitOSImage.Oinitrd = new bx_param_filename_c (BXP_LOAD32BITOS_INITRD, - "Pathname of initrd", - "Pathname of the initial ramdisk", - "", BX_PATHNAME_LEN); - bx_param_c *loader_init_list[] = { - bx_options.load32bitOSImage.OwhichOS, - bx_options.load32bitOSImage.Opath, - bx_options.load32bitOSImage.Oiolog, - bx_options.load32bitOSImage.Oinitrd, - NULL - }; - bx_options.load32bitOSImage.OwhichOS->set_format ("os=%s"); - bx_options.load32bitOSImage.Opath->set_format ("path=%s"); - bx_options.load32bitOSImage.Oiolog->set_format ("iolog=%s"); - bx_options.load32bitOSImage.Oinitrd->set_format ("initrd=%s"); - bx_options.load32bitOSImage.OwhichOS->set_ask_format ("Enter OS to load: [%s] "); - bx_options.load32bitOSImage.Opath->set_ask_format ("Enter pathname of OS: [%s]"); - bx_options.load32bitOSImage.Oiolog->set_ask_format ("Enter pathname of I/O log: [%s] "); - bx_options.load32bitOSImage.Oinitrd->set_ask_format ("Enter pathname of initrd: [%s] "); - menu = new bx_list_c (BXP_LOAD32BITOS, "32-bit OS Loader", "", loader_init_list); - menu->get_options ()->set (menu->SERIES_ASK); - bx_options.load32bitOSImage.OwhichOS->set_handler (bx_param_handler); -#ifdef BX_USE_VMX - bx_options.load32bitOSImage.OwhichOS->set (Load32bitOSLinux); -#else - bx_options.load32bitOSImage.OwhichOS->set (Load32bitOSNone); -#endif - - // clock - bx_options.clock.Otime0 = new bx_param_num_c (BXP_CLOCK_TIME0, - "clock:time0", - "Initial time for Bochs CMOS clock, used if you really want two runs to be identical", - 0, BX_MAX_BIT32U, - BX_CLOCK_TIME0_LOCAL); - bx_options.clock.Osync = new bx_param_enum_c (BXP_CLOCK_SYNC, - "clock:sync", - "Host to guest time synchronization method", - clock_sync_names, - BX_CLOCK_SYNC_NONE, - BX_CLOCK_SYNC_NONE); - bx_param_c *clock_init_list[] = { - bx_options.clock.Osync, - bx_options.clock.Otime0, - NULL - }; -#if !BX_WITH_WX - bx_options.clock.Osync->set_format ("sync=%s"); - bx_options.clock.Otime0->set_format ("initial time=%d"); -#endif - bx_options.clock.Otime0->set_ask_format ("Enter Initial CMOS time (1:localtime, 2:utc, other:time in seconds): [%d] "); - bx_options.clock.Osync->set_ask_format ("Enter Synchronisation method: [%s] "); - bx_options.clock.Otime0->set_label ("Initial CMOS time for Bochs\n(1:localtime, 2:utc, other:time in seconds)"); - bx_options.clock.Osync->set_label ("Synchronisation method"); - menu = new bx_list_c (BXP_CLOCK, "Clock parameters", "", clock_init_list); - menu->get_options ()->set (menu->SERIES_ASK); - - // other - bx_options.Okeyboard_serial_delay = new bx_param_num_c (BXP_KBD_SERIAL_DELAY, - "Keyboard serial delay", - "Approximate time in microseconds that it takes one character to be transfered from the keyboard to controller over the serial path.", - 1, BX_MAX_BIT32U, - 20000); - bx_options.Okeyboard_paste_delay = new bx_param_num_c (BXP_KBD_PASTE_DELAY, - "Keyboard paste delay", - "Approximate time in microseconds between attemps to paste characters to the keyboard controller.", - 1000, BX_MAX_BIT32U, - 100000); - bx_options.Okeyboard_paste_delay->set_handler (bx_param_handler); - bx_options.Okeyboard_paste_delay->set_runtime_param (1); - bx_options.Ofloppy_command_delay = new bx_param_num_c (BXP_FLOPPY_CMD_DELAY, - "Floppy command delay", - "Time in microseconds to wait before completing some floppy commands such as read/write/seek/etc, which normally have a delay associated. This used to be hardwired to 50,000 before.", - 1, BX_MAX_BIT32U, - 50000); - bx_options.Oi440FXSupport = new bx_param_bool_c (BXP_I440FX_SUPPORT, - "PCI i440FX Support", - "Controls whether to emulate the i440FX PCI chipset", - 0); - bx_options.cmos.OcmosImage = new bx_param_bool_c (BXP_CMOS_IMAGE, - "Use a CMOS image", - "Controls the usage of a CMOS image", - 0); - bx_options.cmos.Opath = new bx_param_filename_c (BXP_CMOS_PATH, - "Pathname of CMOS image", - "Pathname of CMOS image", - "", BX_PATHNAME_LEN); - deplist = new bx_list_c (BXP_NULL, 1); - deplist->add (bx_options.cmos.Opath); - bx_options.cmos.OcmosImage->set_dependent_list (deplist); - - // Keyboard mapping - bx_options.keyboard.OuseMapping = new bx_param_bool_c(BXP_KEYBOARD_USEMAPPING, - "Use keyboard mapping", - "Controls whether to use the keyboard mapping feature", - 0); - bx_options.keyboard.Okeymap = new bx_param_filename_c (BXP_KEYBOARD_MAP, - "Keymap filename", - "Pathname of the keymap file used", - "", BX_PATHNAME_LEN); - deplist = new bx_list_c (BXP_NULL, 1); - deplist->add (bx_options.keyboard.Okeymap); - bx_options.keyboard.OuseMapping->set_dependent_list (deplist); - - // Keyboard type - bx_options.Okeyboard_type = new bx_param_enum_c (BXP_KBD_TYPE, - "Keyboard type", - "Keyboard type reported by the 'identify keyboard' command", - keyboard_type_names, - BX_KBD_MF_TYPE, - BX_KBD_XT_TYPE); - bx_options.Okeyboard_type->set_ask_format ("Enter keyboard type: [%s] "); - - // Userbutton shortcut - bx_options.Ouser_shortcut = new bx_param_string_c (BXP_USER_SHORTCUT, - "Userbutton shortcut", - "Defines the keyboard shortcut to be sent when you press the 'user' button in the headerbar.", - "none", 16); - - // GDB stub - bx_options.gdbstub.port = 1234; - bx_options.gdbstub.text_base = 0; - bx_options.gdbstub.data_base = 0; - bx_options.gdbstub.bss_base = 0; - - bx_param_c *keyboard_init_list[] = { - bx_options.Okeyboard_serial_delay, - bx_options.Okeyboard_paste_delay, - bx_options.keyboard.OuseMapping, - bx_options.keyboard.Okeymap, - bx_options.Okeyboard_type, - bx_options.Ouser_shortcut, - NULL - }; - menu = new bx_list_c (BXP_MENU_KEYBOARD, "Configure Keyboard", "", keyboard_init_list); - menu->get_options ()->set (menu->SHOW_PARENT); - - bx_param_c *other_init_list[] = { - bx_options.Ofloppy_command_delay, - bx_options.Oi440FXSupport, - bx_options.cmos.OcmosImage, - bx_options.cmos.Opath, - SIM->get_param (BXP_CLOCK), - SIM->get_param (BXP_LOAD32BITOS), - NULL - }; - menu = new bx_list_c (BXP_MENU_MISC, "Configure Everything Else", "", other_init_list); - menu->get_options ()->set (menu->SHOW_PARENT); - -#if BX_WITH_WX - bx_param_c *other_init_list2[] = { -// bx_options.Osel_config, -// bx_options.Osel_displaylib, - bx_options.Ovga_update_interval, - bx_options.log.Oprefix, - bx_options.Omouse_enabled, - bx_options.OfloppySigCheck, - bx_options.Ofloppy_command_delay, - bx_options.OnewHardDriveSupport, - bx_options.Oprivate_colormap, -#if BX_WITH_AMIGAOS - bx_options.Ofullscreen, - bx_options.Oscreenmode, -#endif - bx_options.Oi440FXSupport, - bx_options.cmos.OcmosImage, - bx_options.cmos.Opath, - NULL - }; - menu = new bx_list_c (BXP_MENU_MISC_2, "Other options", "", other_init_list2); -#endif -} - -void bx_reset_options () -{ - // drives - bx_options.floppya.Opath->reset(); - bx_options.floppya.Odevtype->reset(); - bx_options.floppya.Otype->reset(); - bx_options.floppya.Ostatus->reset(); - bx_options.floppyb.Opath->reset(); - bx_options.floppyb.Odevtype->reset(); - bx_options.floppyb.Otype->reset(); - bx_options.floppyb.Ostatus->reset(); - - for (Bit8u channel=0; channelreset(); - bx_options.ata[channel].Oioaddr1->reset(); - bx_options.ata[channel].Oioaddr2->reset(); - bx_options.ata[channel].Oirq->reset(); - - for (Bit8u slave=0; slave<2; slave++) { - bx_options.atadevice[channel][slave].Opresent->reset(); - bx_options.atadevice[channel][slave].Otype->reset(); - bx_options.atadevice[channel][slave].Omode->reset(); - bx_options.atadevice[channel][slave].Opath->reset(); - bx_options.atadevice[channel][slave].Ocylinders->reset(); - bx_options.atadevice[channel][slave].Oheads->reset(); - bx_options.atadevice[channel][slave].Ospt->reset(); - bx_options.atadevice[channel][slave].Ostatus->reset(); - bx_options.atadevice[channel][slave].Omodel->reset(); - bx_options.atadevice[channel][slave].Obiosdetect->reset(); - bx_options.atadevice[channel][slave].Otranslation->reset(); - } - } - bx_options.OnewHardDriveSupport->reset(); - - // boot & memory - bx_options.Obootdrive->reset(); - bx_options.OfloppySigCheck->reset(); - bx_options.memory.Osize->reset(); - - // standard ports - bx_options.com[0].Oenabled->reset(); - bx_options.com[0].Odev->reset(); - bx_options.par[0].Oenabled->reset(); - bx_options.par[0].Ooutfile->reset(); - - // rom images - bx_options.rom.Opath->reset(); - bx_options.rom.Oaddress->reset(); - bx_options.optrom[0].Opath->reset(); - bx_options.optrom[0].Oaddress->reset(); - bx_options.optrom[1].Opath->reset(); - bx_options.optrom[1].Oaddress->reset(); - bx_options.optrom[2].Opath->reset(); - bx_options.optrom[2].Oaddress->reset(); - bx_options.optrom[3].Opath->reset(); - bx_options.optrom[3].Oaddress->reset(); - bx_options.vgarom.Opath->reset(); - - // interface - bx_options.Ovga_update_interval->reset(); - bx_options.Omouse_enabled->reset(); - bx_options.Oips->reset(); - bx_options.Oprivate_colormap->reset(); -#if BX_WITH_AMIGAOS - bx_options.Ofullscreen->reset(); - bx_options.Oscreenmode->reset(); -#endif - - // ne2k - bx_options.ne2k.Opresent->reset(); - bx_options.ne2k.Oioaddr->reset(); - bx_options.ne2k.Oirq->reset(); - bx_options.ne2k.Omacaddr->reset(); - bx_options.ne2k.Oethmod->reset(); - bx_options.ne2k.Oethdev->reset(); - bx_options.ne2k.Oscript->reset(); - - // SB16 - bx_options.sb16.Opresent->reset(); - bx_options.sb16.Omidifile->reset(); - bx_options.sb16.Owavefile->reset(); - bx_options.sb16.Ologfile->reset(); - bx_options.sb16.Omidimode->reset(); - bx_options.sb16.Owavemode->reset(); - bx_options.sb16.Ologlevel->reset(); - bx_options.sb16.Odmatimer->reset(); - - // logfile - bx_options.log.Ofilename->reset(); - bx_options.log.Oprefix->reset(); - bx_options.log.Odebugger_filename->reset(); - - // loader - bx_options.load32bitOSImage.OwhichOS->reset(); - bx_options.load32bitOSImage.Opath->reset(); - bx_options.load32bitOSImage.Oiolog->reset(); - bx_options.load32bitOSImage.Oinitrd->reset(); - - // keyboard - bx_options.Okeyboard_serial_delay->reset(); - bx_options.Okeyboard_paste_delay->reset(); - bx_options.keyboard.OuseMapping->reset(); - bx_options.keyboard.Okeymap->reset(); - bx_options.Okeyboard_type->reset(); - bx_options.Ouser_shortcut->reset(); - - // Clock - bx_options.clock.Otime0->reset(); - bx_options.clock.Osync->reset(); - - // other - bx_options.Ofloppy_command_delay->reset(); - bx_options.Oi440FXSupport->reset(); - bx_options.cmos.OcmosImage->reset(); - bx_options.cmos.Opath->reset(); - bx_options.Otext_snapshot_check->reset(); -} - -void bx_print_header () -{ - fprintf (stderr, "%s\n", divider); - char buffer[128]; - sprintf (buffer, "Bochs x86 Emulator %s\n", VER_STRING); - bx_center_print (stderr, buffer, 72); - if (REL_STRING[0]) { - sprintf (buffer, "%s\n", REL_STRING); - bx_center_print (stderr, buffer, 72); - } - fprintf (stderr, "%s\n", divider); -} - -#if BX_WITH_CARBON -/* Original code by Darrell Walisser - dwaliss1@purdue.edu */ - -static void setupWorkingDirectory (char *path) -{ - char parentdir[MAXPATHLEN]; - char *c; - - strncpy ( parentdir, path, MAXPATHLEN ); - c = (char*) parentdir; - - while (*c != '\0') /* go to end */ - c++; - - while (*c != '/') /* back up to parent */ - c--; - - *c = '\0'; /* cut off last part (binary name) */ - - /* chdir to the binary app's parent */ - int n; - n = chdir (parentdir); - if (n) BX_PANIC (("failed to change dir to parent")); - /* chdir to the .app's parent */ - n = chdir ("../../../"); - if (n) BX_PANIC (("failed to change to ../../..")); -} - -/* Panic button to display fatal errors. - Completely self contained, can't rely on carbon.cc being available */ -static void carbonFatalDialog(const char *error, const char *exposition) -{ - DialogRef alertDialog; - CFStringRef cfError; - CFStringRef cfExposition; - DialogItemIndex index; - AlertStdCFStringAlertParamRec alertParam = {0}; - fprintf(stderr, "Entering carbonFatalDialog: %s\n", error); - - // Init libraries - InitCursor(); - // Assemble dialog - cfError = CFStringCreateWithCString(NULL, error, kCFStringEncodingASCII); - if(exposition != NULL) - { - cfExposition = CFStringCreateWithCString(NULL, exposition, kCFStringEncodingASCII); - } - else { cfExposition = NULL; } - alertParam.version = kStdCFStringAlertVersionOne; - alertParam.defaultText = CFSTR("Quit"); - alertParam.position = kWindowDefaultPosition; - alertParam.defaultButton = kAlertStdAlertOKButton; - // Display Dialog - CreateStandardAlert( - kAlertStopAlert, - cfError, - cfExposition, /* can be NULL */ - &alertParam, /* can be NULL */ - &alertDialog); - RunStandardAlert( alertDialog, NULL, &index); - // Cleanup - CFRelease( cfError ); - if( cfExposition != NULL ) { CFRelease( cfExposition ); } -} -#endif - -int bxmain () { -#ifdef HAVE_LOCALE_H - // Initialize locale (for isprint() and other functions) - setlocale (LC_ALL, ""); -#endif - bx_user_quit = 0; - bx_init_siminterface (); // create the SIM object - - static jmp_buf context; - if (setjmp (context) == 0) { - SIM->set_quit_context (&context); - if (bx_init_main (bx_startup_flags.argc, bx_startup_flags.argv) < 0) - return 0; - // read a param to decide which config interface to start. - // If one exists, start it. If not, just begin. - bx_param_enum_c *ci_param = SIM->get_param_enum (BXP_SEL_CONFIG_INTERFACE); - char *ci_name = ci_param->get_choice (ci_param->get ()); - if (!strcmp(ci_name, "textconfig")) { - init_text_config_interface (); // in textconfig.h - } -#if BX_WITH_WX - else if (!strcmp(ci_name, "wx")) { - PLUG_load_plugin(wx, PLUGTYPE_CORE); - } -#endif - else { - BX_PANIC (("unsupported configuration interface '%s'", ci_name)); - } - int status = SIM->configuration_interface (ci_name, CI_START); - if (status == CI_ERR_NO_TEXT_CONSOLE) - BX_PANIC (("Bochs needed the text console, but it was not usable")); - // user quit the config interface, so just quit - } else { - // quit via longjmp - } -} - -// normal main function, presently in for all cases except for -// wxWindows under win32. -int main (int argc, char *argv[]) -{ - daemon(0, 0); - bx_startup_flags.argc = argc; - bx_startup_flags.argv = argv; -#if BX_WITH_SDL && defined(WIN32) - // if SDL/win32, try to create a console window. - RedirectIOToConsole (); -#endif - return bxmain (); -} - -void -print_usage () -{ - fprintf(stderr, - "Usage: bochs [flags] [bochsrc options]\n\n" - " -n no configuration file\n" - " -f configfile specify configuration file\n" - " -q quick start (skip configuration interface)\n" - " --help display this help and exit\n\n" - "For information on Bochs configuration file arguments, see the\n" -#if (!defined(WIN32)) && !BX_WITH_MACOS - "bochsrc section in the user documentation or the man page of bochsrc.\n"); -#else - "bochsrc section in the user documentation.\n"); -#endif -} - -#ifdef BX_USE_VMX -int domid = -1; -unsigned long megabytes = 0; -#endif -int -bx_init_main (int argc, char *argv[]) -{ - // To deal with initialization order problems inherent in C++, use the macros - // SAFE_GET_IOFUNC and SAFE_GET_GENLOG to retrieve "io" and "genlog" in all - // constructors or functions called by constructors. The macros test for - // NULL and create the object if necessary, then return it. Ensure that io - // and genlog get created, by making one reference to each macro right here. - // All other code can reference io and genlog directly. Because these - // objects are required for logging, and logging is so fundamental to - // knowing what the program is doing, they are never free()d. - SAFE_GET_IOFUNC(); // never freed - SAFE_GET_GENLOG(); // never freed - - // initalization must be done early because some destructors expect - // the bx_options to exist by the time they are called. - bx_init_bx_dbg (); - bx_init_options (); - - bx_print_header (); - -#ifdef BX_USE_VMX - xc_handle = xc_interface_open(); - SIM->get_param_enum(BXP_BOCHS_START)->set (BX_QUICK_START); -#else - SIM->get_param_enum(BXP_BOCHS_START)->set (BX_RUN_START); -#endif - - // interpret the args that start with -, like -q, -f, etc. - int arg = 1, load_rcfile=1; - while (arg < argc) { - // parse next arg - if (!strcmp ("--help", argv[arg]) || !strncmp ("-h", argv[arg], 2)) { - print_usage(); - SIM->quit_sim (0); - } - else if (!strcmp ("-n", argv[arg])) { - load_rcfile = 0; - } - else if (!strcmp ("-q", argv[arg])) { - SIM->get_param_enum(BXP_BOCHS_START)->set (BX_QUICK_START); - } - else if (!strcmp ("-f", argv[arg])) { - if (++arg >= argc) BX_PANIC(("-f must be followed by a filename")); - else bochsrc_filename = argv[arg]; - } - else if (!strcmp ("-qf", argv[arg])) { - SIM->get_param_enum(BXP_BOCHS_START)->set (BX_QUICK_START); - if (++arg >= argc) BX_PANIC(("-qf must be followed by a filename")); - else bochsrc_filename = argv[arg]; - } -#ifdef BX_USE_VMX - else if (!strcmp ("-p", argv[arg])) { - //get the polling port - extern int ioreq_port; - if (++arg >= argc) BX_PANIC(("-p must be followed by a polling port")); - else sscanf(argv[arg], "%d", &ioreq_port); - } - else if (!strcmp ("-d", argv[arg])) { - //get the domain id - if (++arg >= argc) BX_PANIC(("-d must be followed by domainid")); - else sscanf(argv[arg], "%d", &domid); - } - else if (!strcmp ("-m", argv[arg])) { - //get the maxmem - if (++arg >= argc) - BX_PANIC(("-m must be followed by maxmem in megabytes")); - else sscanf(argv[arg], "%d", &megabytes); - } - -#endif - else if (argv[arg][0] == '-') { - print_usage(); - BX_PANIC (("command line arg '%s' was not understood", argv[arg])); - } - else { - // the arg did not start with -, so stop interpreting flags - break; - } - arg++; - } - - int norcfile = 1; - - if (load_rcfile) { - /* parse configuration file and command line arguments */ -#ifdef WIN32 - if (bochsrc_filename != NULL) { - lstrcpy(bx_startup_flags.initial_dir, bochsrc_filename); - } else { - bx_startup_flags.initial_dir[0] = 0; - } -#endif - if (bochsrc_filename == NULL) bochsrc_filename = bx_find_bochsrc (); - if (bochsrc_filename) - norcfile = bx_read_configuration (bochsrc_filename); - } - - // parse the rest of the command line. This is done after reading the - // configuration file so that the command line arguments can override - // the settings from the file. - if (bx_parse_cmdline (arg, argc, argv)) { - BX_PANIC(("There were errors while parsing the command line")); - return -1; - } - // initialize plugin system. This must happen before we attempt to - // load any modules. - plugin_startup(); - return 0; -} - -bx_bool load_and_init_display_lib () { - if (bx_gui != NULL) { - // bx_gui has already been filled in. This happens when you start - // the simulation for the second time. - // Also, if you load wxWindows as the configuration interface. Its - // plugin_init will install wxWindows as the bx_gui. - return true; - } - BX_ASSERT (bx_gui == NULL); - bx_param_enum_c *ci_param = SIM->get_param_enum (BXP_SEL_CONFIG_INTERFACE); - char *ci_name = ci_param->get_choice (ci_param->get ()); - bx_param_enum_c *gui_param = SIM->get_param_enum(BXP_SEL_DISPLAY_LIBRARY); - char *gui_name = gui_param->get_choice (gui_param->get ()); - if (!strcmp(ci_name, "wx")) { - BX_ERROR(("change of the config interface to wx not implemented yet")); - } - if (!strcmp (gui_name, "wx")) { - // they must not have used wx as the configuration interface, or bx_gui - // would already be initialized. Sorry, it doesn't work that way. - BX_ERROR (("wxWindows was not used as the configuration interface, so it cannot be used as the display library")); - // choose another, hopefully different! - gui_param->set (0); - gui_name = gui_param->get_choice (gui_param->get ()); - if (!strcmp (gui_name, "wx")) { - BX_PANIC (("no alternative display libraries are available")); - return false; - } - BX_ERROR (("changing display library to '%s' instead", gui_name)); - } -#if BX_WITH_NOGUI - if (!strcmp (gui_name, "nogui")) - PLUG_load_plugin (nogui, PLUGTYPE_OPTIONAL); -#endif -#if BX_WITH_RFB - if (!strcmp (gui_name, "rfb")) - PLUG_load_plugin (rfb, PLUGTYPE_OPTIONAL); -#endif -#if BX_WITH_X11 - if (!strcmp (gui_name, "x")) - PLUG_load_plugin (x, PLUGTYPE_OPTIONAL); -#endif -#if BX_WITH_TERM - if (!strcmp (gui_name, "term")) - PLUG_load_plugin (term, PLUGTYPE_OPTIONAL); -#endif - -#if BX_GUI_SIGHANDLER - // set the flag for guis requiring a GUI sighandler. - // useful when guis are compiled as plugins - // only term for now - if (!strcmp (gui_name, "term")) { - bx_gui_sighandler = 1; - } -#endif - - BX_ASSERT (bx_gui != NULL); - return true; -} - -int -bx_begin_simulation (int argc, char *argv[]) -{ - // deal with gui selection - if (!load_and_init_display_lib ()) { - BX_PANIC (("no gui module was loaded")); - return 0; - } -#if BX_GDBSTUB - // If using gdbstub, it will take control and call - // bx_init_hardware() and cpu_loop() - bx_gdbstub_init (argc, argv); -#elif BX_DEBUGGER - // If using the debugger, it will take control and call - // bx_init_hardware() and cpu_loop() - bx_dbg_main(argc, argv); -#else - - bx_init_hardware(); - - if (bx_options.load32bitOSImage.OwhichOS->get ()) { - void bx_load32bitOSimagehack(void); - bx_load32bitOSimagehack(); - } - - SIM->set_init_done (1); - - // update headerbar buttons since drive status can change during init - bx_gui->update_drive_status_buttons (); - - // The set handler for mouse_enabled does not actually update the gui - // until init_done is set. This forces the set handler to be called, - // which sets up the mouse enabled GUI-specific stuff correctly. - // Not a great solution but it works. BBD - bx_options.Omouse_enabled->set (bx_options.Omouse_enabled->get ()); - - if (BX_SMP_PROCESSORS == 1) { - // only one processor, run as fast as possible by not messing with - // quantums and loops. - BX_CPU(0)->cpu_loop(1); - // for one processor, the only reason for cpu_loop to return is - // that kill_bochs_request was set by the GUI interface. - } else { - // SMP simulation: do a few instructions on each processor, then switch - // to another. Increasing quantum speeds up overall performance, but - // reduces granularity of synchronization between processors. - int processor = 0; - int quantum = 5; - while (1) { - // do some instructions in each processor - BX_CPU(processor)->cpu_loop(quantum); - processor = (processor+1) % BX_SMP_PROCESSORS; - if (BX_CPU(0)->kill_bochs_request) - break; - if (processor == 0) - BX_TICKN(quantum); - } - } -#endif - BX_INFO (("cpu loop quit, shutting down simulator")); - bx_atexit (); - return(0); -} - - -int -bx_read_configuration (char *rcfile) -{ - // parse rcfile first, then parse arguments in order. - BX_INFO (("reading configuration from %s", rcfile)); - if (parse_bochsrc(rcfile) < 0) { - BX_PANIC (("reading from %s failed", rcfile)); - return -1; - } - // update log actions - for (int level=0; levelget_default_log_action (level); - io->set_log_action (level, action); - } - return 0; -} - -int bx_parse_cmdline (int arg, int argc, char *argv[]) -{ - //if (arg < argc) BX_INFO (("parsing command line arguments")); - - while (arg < argc) { - BX_INFO (("parsing arg %d, %s", arg, argv[arg])); - parse_line_unformatted("cmdline args", argv[arg]); - arg++; - } - // update log actions - for (int level=0; levelget_default_log_action (level); - io->set_log_action (level, action); - } - return 0; -} - - int -bx_init_hardware() -{ - // all configuration has been read, now initialize everything. - - if (SIM->get_param_enum(BXP_BOCHS_START)->get ()==BX_QUICK_START) { - for (int level=0; levelget_default_log_action (level); -#if !BX_USE_CONFIG_INTERFACE - if (action == ACT_ASK) action = ACT_FATAL; -#endif - io->set_log_action (level, action); - } - } - - bx_pc_system.init_ips(bx_options.Oips->get ()); - - if(bx_options.log.Ofilename->getptr()[0]!='-') { - BX_INFO (("using log file %s", bx_options.log.Ofilename->getptr ())); - io->init_log(bx_options.log.Ofilename->getptr ()); - } - - io->set_log_prefix(bx_options.log.Oprefix->getptr()); - - // Output to the log file the cpu settings - // This will by handy for bug reports - BX_INFO(("Bochs x86 Emulator %s", VER_STRING)); - BX_INFO((" %s", REL_STRING)); - BX_INFO(("System configuration")); - BX_INFO((" processors: %d",BX_SMP_PROCESSORS)); - BX_INFO((" A20 line support: %s",BX_SUPPORT_A20?"yes":"no")); - BX_INFO((" APIC support: %s",BX_SUPPORT_APIC?"yes":"no")); - -#ifndef BX_USE_VMX - BX_INFO(("CPU configuration")); - BX_INFO((" level: %d",BX_CPU_LEVEL)); - BX_INFO((" fpu support: %s",BX_SUPPORT_FPU?"yes":"no")); - BX_INFO((" paging support: %s, tlb enabled: %s",BX_SUPPORT_PAGING?"yes":"no",BX_USE_TLB?"yes":"no")); - BX_INFO((" mmx support: %s",BX_SUPPORT_MMX?"yes":"no")); - BX_INFO((" sse support: %s",BX_SUPPORT_SSE==2?"2":BX_SUPPORT_SSE==1?"1":"no")); - BX_INFO((" v8086 mode support: %s",BX_SUPPORT_V8086_MODE?"yes":"no")); - BX_INFO((" 3dnow! support: %s",BX_SUPPORT_3DNOW?"yes":"no")); - BX_INFO((" PAE support: %s",BX_SupportPAE?"yes":"no")); - BX_INFO((" PGE support: %s",BX_SupportGlobalPages?"yes":"no")); - BX_INFO((" PSE support: %s",BX_SUPPORT_4MEG_PAGES?"yes":"no")); - BX_INFO((" x86-64 support: %s",BX_SUPPORT_X86_64?"yes":"no")); - BX_INFO((" SEP support: %s",BX_SUPPORT_SEP?"yes":"no")); - BX_INFO(("Optimization configuration")); - BX_INFO((" Guest2HostTLB support: %s",BX_SupportGuest2HostTLB?"yes":"no")); - BX_INFO((" RepeatSpeedups support: %s",BX_SupportRepeatSpeedups?"yes":"no")); - BX_INFO((" Icache support: %s",BX_SupportICache?"yes":"no")); - BX_INFO((" Host Asm support: %s",BX_SupportHostAsms?"yes":"no")); -#endif /* BX_USE_VMX */ - - // set up memory and CPU objects -#if BX_SUPPORT_APIC - bx_generic_apic_c::reset_all_ids (); -#endif - -#ifndef BX_USE_VMX - // Check if there is a romimage - if (strcmp(bx_options.rom.Opath->getptr (),"") == 0) { - BX_ERROR(("No romimage to load. Is your bochsrc file loaded/valid ?")); - } - -#if BX_SMP_PROCESSORS==1 - BX_MEM(0)->init_memory(bx_options.memory.Osize->get () * 1024*1024); - - // First load the optional ROM images - if (strcmp(bx_options.optrom[0].Opath->getptr (),"") !=0 ) - BX_MEM(0)->load_ROM(bx_options.optrom[0].Opath->getptr (), bx_options.optrom[0].Oaddress->get (), 2); - if (strcmp(bx_options.optrom[1].Opath->getptr (),"") !=0 ) - BX_MEM(0)->load_ROM(bx_options.optrom[1].Opath->getptr (), bx_options.optrom[1].Oaddress->get (), 2); - if (strcmp(bx_options.optrom[2].Opath->getptr (),"") !=0 ) - BX_MEM(0)->load_ROM(bx_options.optrom[2].Opath->getptr (), bx_options.optrom[2].Oaddress->get (), 2); - if (strcmp(bx_options.optrom[3].Opath->getptr (),"") !=0 ) - BX_MEM(0)->load_ROM(bx_options.optrom[3].Opath->getptr (), bx_options.optrom[3].Oaddress->get (), 2); - - // Then Load the BIOS and VGABIOS - BX_MEM(0)->load_ROM(bx_options.rom.Opath->getptr (), bx_options.rom.Oaddress->get (), 0); - BX_MEM(0)->load_ROM(bx_options.vgarom.Opath->getptr (), 0xc0000, 1); - - BX_CPU(0)->init (BX_MEM(0)); - BX_CPU(0)->set_cpu_id(0); -#if BX_SUPPORT_APIC - BX_CPU(0)->local_apic.set_id (0); -#endif - BX_INSTR_INIT(0); - BX_CPU(0)->reset(BX_RESET_HARDWARE); -#else - // SMP initialization - bx_mem_array[0] = new BX_MEM_C (); - bx_mem_array[0]->init_memory(bx_options.memory.Osize->get () * 1024*1024); - - // First load the optional ROM images - if (strcmp(bx_options.optrom[0].Opath->getptr (),"") !=0 ) - bx_mem_array[0]->load_ROM(bx_options.optrom[0].Opath->getptr (), bx_options.optrom[0].Oaddress->get (), 2); - if (strcmp(bx_options.optrom[1].Opath->getptr (),"") !=0 ) - bx_mem_array[0]->load_ROM(bx_options.optrom[1].Opath->getptr (), bx_options.optrom[1].Oaddress->get (), 2); - if (strcmp(bx_options.optrom[2].Opath->getptr (),"") !=0 ) - bx_mem_array[0]->load_ROM(bx_options.optrom[2].Opath->getptr (), bx_options.optrom[2].Oaddress->get (), 2); - if (strcmp(bx_options.optrom[3].Opath->getptr (),"") !=0 ) - bx_mem_array[0]->load_ROM(bx_options.optrom[3].Opath->getptr (), bx_options.optrom[3].Oaddress->get (), 2); - - // Then Load the BIOS and VGABIOS - bx_mem_array[0]->load_ROM(bx_options.rom.Opath->getptr (), bx_options.rom.Oaddress->get (), 0); - bx_mem_array[0]->load_ROM(bx_options.vgarom.Opath->getptr (), 0xc0000, 1); - - for (int i=0; iinit (bx_mem_array[0]); - // assign apic ID from the index of this loop - // if !BX_SUPPORT_APIC, this will not compile. - BX_CPU(i)->set_cpu_id(i); - BX_CPU(i)->local_apic.set_id (i); - BX_INSTR_INIT(i); - BX_CPU(i)->reset(BX_RESET_HARDWARE); - } -#endif -#else - // Assume UP for now for VMX - bx_mem.init_memory(megabytes * 1024 * 1024); - bx_cpu.init(&bx_mem); -#endif // BX_USE_VMX - -#if BX_DEBUGGER == 0 - DEV_init_devices(); - DEV_reset_devices(BX_RESET_HARDWARE); - bx_gui->init_signal_handlers (); - bx_pc_system.start_timers(); -#endif - BX_DEBUG(("bx_init_hardware is setting signal handlers")); -// if not using debugger, then we can take control of SIGINT. -#if !BX_DEBUGGER - signal(SIGINT, bx_signal_handler); -#endif - -#if BX_SHOW_IPS -#ifndef __MINGW32__ - signal(SIGALRM, bx_signal_handler); -#endif - alarm( 1 ); -#endif - - return(0); -} - - - - void -bx_init_bx_dbg (void) -{ - bx_dbg.floppy = 0; - bx_dbg.keyboard = 0; - bx_dbg.video = 0; - bx_dbg.disk = 0; - bx_dbg.pit = 0; - bx_dbg.pic = 0; - bx_dbg.bios = 0; - bx_dbg.cmos = 0; - bx_dbg.a20 = 0; - bx_dbg.interrupts = 0; - bx_dbg.exceptions = 0; - bx_dbg.unsupported = 0; - bx_dbg.temp = 0; - bx_dbg.reset = 0; - bx_dbg.mouse = 0; - bx_dbg.io = 0; - bx_dbg.debugger = 0; - bx_dbg.xms = 0; - bx_dbg.v8086 = 0; - bx_dbg.paging = 0; - bx_dbg.creg = 0; - bx_dbg.dreg = 0; - bx_dbg.dma = 0; - bx_dbg.unsupported_io = 0; - bx_dbg.record_io = 0; - bx_dbg.serial = 0; - bx_dbg.cdrom = 0; -#ifdef MAGIC_BREAKPOINT - bx_dbg.magic_break_enabled = 0; -#endif - -} - - -int -bx_atexit(void) -{ - static bx_bool been_here = 0; - if (been_here) return 1; // protect from reentry - been_here = 1; - - // in case we ended up in simulation mode, change back to config mode - // so that the user can see any messages left behind on the console. - SIM->set_display_mode (DISP_MODE_CONFIG); - -#if BX_PROVIDE_DEVICE_MODELS==1 - bx_pc_system.exit(); -#endif - -#if BX_DEBUGGER == 0 - if (SIM && SIM->get_init_done ()) { - for (int cpu=0; cpuatexit(); - } -#endif - -#if BX_PCI_SUPPORT - if (bx_options.Oi440FXSupport->get ()) { - bx_devices.pluginPciBridge->print_i440fx_state(); - } -#endif - - // restore signal handling to defaults -#if !BX_DEBUGGER - BX_INFO (("restoring default signal behavior")); - signal(SIGINT, SIG_DFL); -#endif - -#if BX_SHOW_IPS -#ifndef __MINGW32__ - signal(SIGALRM, SIG_DFL); -#endif -#endif - return 0; -} - -#if BX_PROVIDE_MAIN - -char * -bx_find_bochsrc () -{ - FILE *fd = NULL; - char rcfile[512]; - Bit32u retry = 0, found = 0; - // try several possibilities for the bochsrc before giving up - while (!found) { - rcfile[0] = 0; - switch (retry++) { - case 0: strcpy (rcfile, ".bochsrc"); break; - case 1: strcpy (rcfile, "bochsrc"); break; - case 2: strcpy (rcfile, "bochsrc.txt"); break; -#ifdef WIN32 - case 3: strcpy (rcfile, "bochsrc.bxrc"); break; -#elif !BX_WITH_MACOS - // only try this on unix - case 3: - { - char *ptr = getenv("HOME"); - if (ptr) snprintf (rcfile, sizeof(rcfile), "%s/.bochsrc", ptr); - } - break; - case 4: strcpy (rcfile, "/etc/bochsrc"); break; -#endif - default: - return NULL; - } - if (rcfile[0]) { - BX_DEBUG (("looking for configuration in %s", rcfile)); - fd = fopen(rcfile, "r"); - if (fd) found = 1; - } - } - assert (fd != NULL && rcfile[0] != 0); - fclose (fd); - return strdup (rcfile); -} - - static int -parse_bochsrc(char *rcfile) -{ - FILE *fd = NULL; - char *ret; - char line[512]; - - // try several possibilities for the bochsrc before giving up - - bochsrc_include_count++; - - fd = fopen (rcfile, "r"); - if (fd == NULL) return -1; - - int retval = 0; - do { - ret = fgets(line, sizeof(line)-1, fd); - line[sizeof(line) - 1] = '\0'; - int len = strlen(line); - if (len>0) - line[len-1] = '\0'; - if ((ret != NULL) && strlen(line)) { - if (parse_line_unformatted(rcfile, line) < 0) { - retval = -1; - break; // quit parsing after first error - } - } - } while (!feof(fd)); - fclose(fd); - bochsrc_include_count--; - return retval; -} - - static Bit32s -parse_line_unformatted(char *context, char *line) -{ -#define MAX_PARAMS_LEN 40 - char *ptr; - unsigned i, string_i; - char string[512]; - char *params[MAX_PARAMS_LEN]; - int num_params; - bx_bool inquotes = 0; - bx_bool comment = 0; - - memset(params, 0, sizeof(params)); - if (line == NULL) return 0; - - // if passed nothing but whitespace, just return - for (i=0; i=strlen(line)) - return 0; - - num_params = 0; - - if (!strncmp(line, "#include", 8)) - ptr = strtok(line, " "); - else - ptr = strtok(line, ":"); - while ((ptr) && (!comment)) { - string_i = 0; - for (i=0; iset (BX_EJECTED); - } - else if (!strncmp(params[i], "status=inserted", 15)) { - bx_options.floppya.Ostatus->set (BX_INSERTED); - } - else { - PARSE_ERR(("%s: floppya attribute '%s' not understood.", context, - params[i])); - } - } - } - else if (!strcmp(params[0], "gdbstub_port")) - { - if (num_params != 2) - { - fprintf(stderr, ".bochsrc: gdbstub_port directive: wrong # args.\n"); - exit(1); - } - bx_options.gdbstub.port = atoi(params[1]); - } - else if (!strcmp(params[0], "gdbstub_text_base")) - { - if (num_params != 2) - { - fprintf(stderr, ".bochsrc: gdbstub_text_base directive: wrong # args.\n"); - exit(1); - } - bx_options.gdbstub.text_base = atoi(params[1]); - } - else if (!strcmp(params[0], "gdbstub_data_base")) - { - if (num_params != 2) - { - fprintf(stderr, ".bochsrc: gdbstub_data_base directive: wrong # args.\n"); - exit(1); - } - bx_options.gdbstub.data_base = atoi(params[1]); - } - else if (!strcmp(params[0], "gdbstub_bss_base")) - { - if (num_params != 2) - { - fprintf(stderr, ".bochsrc: gdbstub_bss_base directive: wrong # args.\n"); - exit(1); - } - bx_options.gdbstub.bss_base = atoi(params[1]); - } - - else if (!strcmp(params[0], "floppyb")) { - for (i=1; iset (BX_EJECTED); - } - else if (!strncmp(params[i], "status=inserted", 15)) { - bx_options.floppyb.Ostatus->set (BX_INSERTED); - } - else { - PARSE_ERR(("%s: floppyb attribute '%s' not understood.", context, - params[i])); - } - } - } - - else if ((!strncmp(params[0], "ata", 3)) && (strlen(params[0]) == 4)) { - Bit8u channel = params[0][3]; - - if ((channel < '0') || (channel > '9')) { - PARSE_ERR(("%s: ataX directive malformed.", context)); - } - channel-='0'; - if (channel >= BX_MAX_ATA_CHANNEL) { - PARSE_ERR(("%s: ataX directive malformed.", context)); - } - - if ((num_params < 2) || (num_params > 5)) { - PARSE_ERR(("%s: ataX directive malformed.", context)); - } - - if (strncmp(params[1], "enabled=", 8)) { - PARSE_ERR(("%s: ataX directive malformed.", context)); - } - else { - bx_options.ata[channel].Opresent->set (atol(¶ms[1][8])); - } - - if (num_params > 2) { - if (strncmp(params[2], "ioaddr1=", 8)) { - PARSE_ERR(("%s: ataX directive malformed.", context)); - } - else { - if ( (params[2][8] == '0') && (params[2][9] == 'x') ) - bx_options.ata[channel].Oioaddr1->set (strtoul (¶ms[2][8], NULL, 16)); - else - bx_options.ata[channel].Oioaddr1->set (strtoul (¶ms[2][8], NULL, 10)); - } - } - - if (num_params > 3) { - if (strncmp(params[3], "ioaddr2=", 8)) { - PARSE_ERR(("%s: ataX directive malformed.", context)); - } - else { - if ( (params[3][8] == '0') && (params[3][9] == 'x') ) - bx_options.ata[channel].Oioaddr2->set (strtoul (¶ms[3][8], NULL, 16)); - else - bx_options.ata[channel].Oioaddr2->set (strtoul (¶ms[3][8], NULL, 10)); - } - } - - if (num_params > 4) { - if (strncmp(params[4], "irq=", 4)) { - PARSE_ERR(("%s: ataX directive malformed.", context)); - } - else { - bx_options.ata[channel].Oirq->set (atol(¶ms[4][4])); - } - } - } - - // ataX-master, ataX-slave - else if ((!strncmp(params[0], "ata", 3)) && (strlen(params[0]) > 4)) { - Bit8u channel = params[0][3], slave = 0; - - if ((channel < '0') || (channel > '9')) { - PARSE_ERR(("%s: ataX-master/slave directive malformed.", context)); - } - channel-='0'; - if (channel >= BX_MAX_ATA_CHANNEL) { - PARSE_ERR(("%s: ataX-master/slave directive malformed.", context)); - } - - if ((strcmp(¶ms[0][4], "-slave")) && - (strcmp(¶ms[0][4], "-master"))) { - PARSE_ERR(("%s: ataX-master/slave directive malformed.", context)); - } - - if (!strcmp(¶ms[0][4], "-slave")) { - slave = 1; - } - - // This was originally meant to warn users about both diskc - // and ata0-master defined, but it also prevent users to - // override settings on the command line - // (see [ 661010 ] cannot override ata-settings from cmdline) - // if (bx_options.atadevice[channel][slave].Opresent->get()) { - // BX_INFO(("%s: %s device of ata channel %d already defined.", context, slave?"slave":"master",channel)); - // } - - for (i=1; iset (BX_ATA_DEVICE_DISK); - } - else if (!strcmp(params[i], "type=cdrom")) { - bx_options.atadevice[channel][slave].Otype->set (BX_ATA_DEVICE_CDROM); - } - else if (!strcmp(params[i], "mode=flat")) { - bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_FLAT); - } - else if (!strcmp(params[i], "mode=concat")) { - bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_CONCAT); - } - else if (!strcmp(params[i], "mode=external")) { - bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_EXTDISKSIM); - } - else if (!strcmp(params[i], "mode=dll")) { - bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_DLL_HD); - } - else if (!strcmp(params[i], "mode=sparse")) { - bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_SPARSE); - } - else if (!strcmp(params[i], "mode=vmware3")) { - bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_VMWARE3); - } -// else if (!strcmp(params[i], "mode=split")) { -// bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_SPLIT); -// } - else if (!strcmp(params[i], "mode=undoable")) { - bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_UNDOABLE); - } - else if (!strcmp(params[i], "mode=growing")) { - bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_GROWING); - } - else if (!strcmp(params[i], "mode=volatile")) { - bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_VOLATILE); - } -// else if (!strcmp(params[i], "mode=z-undoable")) { -// bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_Z_UNDOABLE); -// } -// else if (!strcmp(params[i], "mode=z-volatile")) { -// bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_Z_VOLATILE); -// } - else if (!strncmp(params[i], "path=", 5)) { - bx_options.atadevice[channel][slave].Opath->set (¶ms[i][5]); - } - else if (!strncmp(params[i], "cylinders=", 10)) { - bx_options.atadevice[channel][slave].Ocylinders->set (atol(¶ms[i][10])); - } - else if (!strncmp(params[i], "heads=", 6)) { - bx_options.atadevice[channel][slave].Oheads->set (atol(¶ms[i][6])); - } - else if (!strncmp(params[i], "spt=", 4)) { - bx_options.atadevice[channel][slave].Ospt->set (atol(¶ms[i][4])); - } - else if (!strncmp(params[i], "model=", 6)) { - bx_options.atadevice[channel][slave].Omodel->set(¶ms[i][6]); - } - else if (!strcmp(params[i], "biosdetect=none")) { - bx_options.atadevice[channel][slave].Obiosdetect->set(BX_ATA_BIOSDETECT_NONE); - } - else if (!strcmp(params[i], "biosdetect=cmos")) { - bx_options.atadevice[channel][slave].Obiosdetect->set(BX_ATA_BIOSDETECT_CMOS); - } - else if (!strcmp(params[i], "biosdetect=auto")) { - bx_options.atadevice[channel][slave].Obiosdetect->set(BX_ATA_BIOSDETECT_AUTO); - } - else if (!strcmp(params[i], "translation=none")) { - bx_options.atadevice[channel][slave].Otranslation->set(BX_ATA_TRANSLATION_NONE); - } - else if (!strcmp(params[i], "translation=lba")) { - bx_options.atadevice[channel][slave].Otranslation->set(BX_ATA_TRANSLATION_LBA); - } - else if (!strcmp(params[i], "translation=large")) { - bx_options.atadevice[channel][slave].Otranslation->set(BX_ATA_TRANSLATION_LARGE); - } - else if (!strcmp(params[i], "translation=echs")) { // synonym of large - bx_options.atadevice[channel][slave].Otranslation->set(BX_ATA_TRANSLATION_LARGE); - } - else if (!strcmp(params[i], "translation=rechs")) { - bx_options.atadevice[channel][slave].Otranslation->set(BX_ATA_TRANSLATION_RECHS); - } - else if (!strcmp(params[i], "translation=auto")) { - bx_options.atadevice[channel][slave].Otranslation->set(BX_ATA_TRANSLATION_AUTO); - } - else if (!strcmp(params[i], "status=ejected")) { - bx_options.atadevice[channel][slave].Ostatus->set(BX_EJECTED); - } - else if (!strcmp(params[i], "status=inserted")) { - bx_options.atadevice[channel][slave].Ostatus->set(BX_INSERTED); - } - else if (!strncmp(params[i], "journal=", 8)) { - bx_options.atadevice[channel][slave].Ojournal->set(¶ms[i][8]); - } - else { - PARSE_ERR(("%s: ataX-master/slave directive malformed.", context)); - } - } - - // Enables the ata device - bx_options.atadevice[channel][slave].Opresent->set(1); - - // if enabled, check if device ok - if (bx_options.atadevice[channel][slave].Opresent->get() == 1) { - if (bx_options.atadevice[channel][slave].Otype->get() == BX_ATA_DEVICE_DISK) { - if (strlen(bx_options.atadevice[channel][slave].Opath->getptr()) ==0) - PARSE_WARN(("%s: ataX-master/slave has empty path", context)); - if ((bx_options.atadevice[channel][slave].Ocylinders->get() == 0) || - (bx_options.atadevice[channel][slave].Oheads->get() ==0 ) || - (bx_options.atadevice[channel][slave].Ospt->get() == 0)) { - PARSE_WARN(("%s: ataX-master/slave cannot have zero cylinders, heads, or sectors/track", context)); - } - } - else if (bx_options.atadevice[channel][slave].Otype->get() == BX_ATA_DEVICE_CDROM) { - if (strlen(bx_options.atadevice[channel][slave].Opath->getptr()) == 0) { - PARSE_WARN(("%s: ataX-master/slave has empty path", context)); - } - } - else { - PARSE_WARN(("%s: ataX-master/slave: type should be specified", context)); - } - } - } - - // Legacy disk options emulation - else if (!strcmp(params[0], "diskc")) { // DEPRECATED - BX_INFO(("WARNING: diskc directive is deprecated, use ata0-master: instead")); - if (bx_options.atadevice[0][0].Opresent->get()) { - PARSE_ERR(("%s: master device of ata channel 0 already defined.", context)); - } - if (num_params != 5) { - PARSE_ERR(("%s: diskc directive malformed.", context)); - } - if (strncmp(params[1], "file=", 5) || - strncmp(params[2], "cyl=", 4) || - strncmp(params[3], "heads=", 6) || - strncmp(params[4], "spt=", 4)) { - PARSE_ERR(("%s: diskc directive malformed.", context)); - } - bx_options.ata[0].Opresent->set(1); - bx_options.atadevice[0][0].Otype->set (BX_ATA_DEVICE_DISK); - bx_options.atadevice[0][0].Opath->set (¶ms[1][5]); - bx_options.atadevice[0][0].Ocylinders->set (atol(¶ms[2][4])); - bx_options.atadevice[0][0].Oheads->set (atol(¶ms[3][6])); - bx_options.atadevice[0][0].Ospt->set (atol(¶ms[4][4])); - bx_options.atadevice[0][0].Opresent->set (1); - } - else if (!strcmp(params[0], "diskd")) { // DEPRECATED - BX_INFO(("WARNING: diskd directive is deprecated, use ata0-slave: instead")); - if (bx_options.atadevice[0][1].Opresent->get()) { - PARSE_ERR(("%s: slave device of ata channel 0 already defined.", context)); - } - if (num_params != 5) { - PARSE_ERR(("%s: diskd directive malformed.", context)); - } - if (strncmp(params[1], "file=", 5) || - strncmp(params[2], "cyl=", 4) || - strncmp(params[3], "heads=", 6) || - strncmp(params[4], "spt=", 4)) { - PARSE_ERR(("%s: diskd directive malformed.", context)); - } - bx_options.ata[0].Opresent->set(1); - bx_options.atadevice[0][1].Otype->set (BX_ATA_DEVICE_DISK); - bx_options.atadevice[0][1].Opath->set (¶ms[1][5]); - bx_options.atadevice[0][1].Ocylinders->set (atol( ¶ms[2][4])); - bx_options.atadevice[0][1].Oheads->set (atol( ¶ms[3][6])); - bx_options.atadevice[0][1].Ospt->set (atol( ¶ms[4][4])); - bx_options.atadevice[0][1].Opresent->set (1); - } - else if (!strcmp(params[0], "cdromd")) { // DEPRECATED - BX_INFO(("WARNING: cdromd directive is deprecated, use ata0-slave: instead")); - if (bx_options.atadevice[0][1].Opresent->get()) { - PARSE_ERR(("%s: slave device of ata channel 0 already defined.", context)); - } - if (num_params != 3) { - PARSE_ERR(("%s: cdromd directive malformed.", context)); - } - if (strncmp(params[1], "dev=", 4) || strncmp(params[2], "status=", 7)) { - PARSE_ERR(("%s: cdromd directive malformed.", context)); - } - bx_options.ata[0].Opresent->set(1); - bx_options.atadevice[0][1].Otype->set (BX_ATA_DEVICE_CDROM); - bx_options.atadevice[0][1].Opath->set (¶ms[1][4]); - if (!strcmp(params[2], "status=inserted")) - bx_options.atadevice[0][1].Ostatus->set (BX_INSERTED); - else if (!strcmp(params[2], "status=ejected")) - bx_options.atadevice[0][1].Ostatus->set (BX_EJECTED); - else { - PARSE_ERR(("%s: cdromd directive malformed.", context)); - } - bx_options.atadevice[0][1].Opresent->set (1); - } - - else if (!strcmp(params[0], "boot")) { - if (!strcmp(params[1], "a")) { - bx_options.Obootdrive->set (BX_BOOT_FLOPPYA); - } else if (!strcmp(params[1], "floppy")) { - bx_options.Obootdrive->set (BX_BOOT_FLOPPYA); - } else if (!strcmp(params[1], "c")) { - bx_options.Obootdrive->set (BX_BOOT_DISKC); - } else if (!strcmp(params[1], "disk")) { - bx_options.Obootdrive->set (BX_BOOT_DISKC); - } else if (!strcmp(params[1], "cdrom")) { - bx_options.Obootdrive->set (BX_BOOT_CDROM); - } else { - PARSE_ERR(("%s: boot directive with unknown boot device '%s'. use 'floppy', 'disk' or 'cdrom'.", context, params[1])); - } - } - - else if (!strcmp(params[0], "com1")) { - for (i=1; iset (0); - else if (params[1][9] == '1') - bx_options.OfloppySigCheck->set (1); - else { - PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context)); - } - } - else if (!strcmp(params[0], "log")) { - if (num_params != 2) { - PARSE_ERR(("%s: log directive has wrong # args.", context)); - } - bx_options.log.Ofilename->set (params[1]); - } - else if (!strcmp(params[0], "logprefix")) { - if (num_params != 2) { - PARSE_ERR(("%s: logprefix directive has wrong # args.", context)); - } - bx_options.log.Oprefix->set (params[1]); - } - else if (!strcmp(params[0], "debugger_log")) { - if (num_params != 2) { - PARSE_ERR(("%s: debugger_log directive has wrong # args.", context)); - } - bx_options.log.Odebugger_filename->set (params[1]); - } - else if (!strcmp(params[0], "panic")) { - if (num_params != 2) { - PARSE_ERR(("%s: panic directive malformed.", context)); - } - if (strncmp(params[1], "action=", 7)) { - PARSE_ERR(("%s: panic directive malformed.", context)); - } - char *action = 7 + params[1]; - if (!strcmp(action, "fatal")) - SIM->set_default_log_action (LOGLEV_PANIC, ACT_FATAL); - else if (!strcmp (action, "report")) - SIM->set_default_log_action (LOGLEV_PANIC, ACT_REPORT); - else if (!strcmp (action, "ignore")) - SIM->set_default_log_action (LOGLEV_PANIC, ACT_IGNORE); - else if (!strcmp (action, "ask")) - SIM->set_default_log_action (LOGLEV_PANIC, ACT_ASK); - else { - PARSE_ERR(("%s: panic directive malformed.", context)); - } - } - else if (!strcmp(params[0], "pass")) { - if (num_params != 2) { - PARSE_ERR(("%s: pass directive malformed.", context)); - } - if (strncmp(params[1], "action=", 7)) { - PARSE_ERR(("%s: pass directive malformed.", context)); - } - char *action = 7 + params[1]; - if (!strcmp(action, "fatal")) - SIM->set_default_log_action (LOGLEV_PASS, ACT_FATAL); - else if (!strcmp (action, "report")) - SIM->set_default_log_action (LOGLEV_PASS, ACT_REPORT); - else if (!strcmp (action, "ignore")) - SIM->set_default_log_action (LOGLEV_PASS, ACT_IGNORE); - else if (!strcmp (action, "ask")) - SIM->set_default_log_action (LOGLEV_PASS, ACT_ASK); - else { - PARSE_ERR(("%s: pass directive malformed.", context)); - } - } - else if (!strcmp(params[0], "error")) { - if (num_params != 2) { - PARSE_ERR(("%s: error directive malformed.", context)); - } - if (strncmp(params[1], "action=", 7)) { - PARSE_ERR(("%s: error directive malformed.", context)); - } - char *action = 7 + params[1]; - if (!strcmp(action, "fatal")) - SIM->set_default_log_action (LOGLEV_ERROR, ACT_FATAL); - else if (!strcmp (action, "report")) - SIM->set_default_log_action (LOGLEV_ERROR, ACT_REPORT); - else if (!strcmp (action, "ignore")) - SIM->set_default_log_action (LOGLEV_ERROR, ACT_IGNORE); - else if (!strcmp (action, "ask")) - SIM->set_default_log_action (LOGLEV_ERROR, ACT_ASK); - else { - PARSE_ERR(("%s: error directive malformed.", context)); - } - } - else if (!strcmp(params[0], "info")) { - if (num_params != 2) { - PARSE_ERR(("%s: info directive malformed.", context)); - } - if (strncmp(params[1], "action=", 7)) { - PARSE_ERR(("%s: info directive malformed.", context)); - } - char *action = 7 + params[1]; - if (!strcmp(action, "fatal")) - SIM->set_default_log_action (LOGLEV_INFO, ACT_FATAL); - else if (!strcmp (action, "report")) - SIM->set_default_log_action (LOGLEV_INFO, ACT_REPORT); - else if (!strcmp (action, "ignore")) - SIM->set_default_log_action (LOGLEV_INFO, ACT_IGNORE); - else if (!strcmp (action, "ask")) - SIM->set_default_log_action (LOGLEV_INFO, ACT_ASK); - else { - PARSE_ERR(("%s: info directive malformed.", context)); - } - } - else if (!strcmp(params[0], "debug")) { - if (num_params != 2) { - PARSE_ERR(("%s: debug directive malformed.", context)); - } - if (strncmp(params[1], "action=", 7)) { - PARSE_ERR(("%s: debug directive malformed.", context)); - } - char *action = 7 + params[1]; - if (!strcmp(action, "fatal")) - SIM->set_default_log_action (LOGLEV_DEBUG, ACT_FATAL); - else if (!strcmp (action, "report")) - SIM->set_default_log_action (LOGLEV_DEBUG, ACT_REPORT); - else if (!strcmp (action, "ignore")) - SIM->set_default_log_action (LOGLEV_DEBUG, ACT_IGNORE); - else if (!strcmp (action, "ask")) - SIM->set_default_log_action (LOGLEV_DEBUG, ACT_ASK); - else { - PARSE_ERR(("%s: debug directive malformed.", context)); - } - } - else if (!strcmp(params[0], "romimage")) { - if (num_params != 3) { - PARSE_ERR(("%s: romimage directive: wrong # args.", context)); - } - if (strncmp(params[1], "file=", 5)) { - PARSE_ERR(("%s: romimage directive malformed.", context)); - } - if (strncmp(params[2], "address=", 8)) { - PARSE_ERR(("%s: romimage directive malformed.", context)); - } - bx_options.rom.Opath->set (¶ms[1][5]); - if ( (params[2][8] == '0') && (params[2][9] == 'x') ) - bx_options.rom.Oaddress->set (strtoul (¶ms[2][8], NULL, 16)); - else - bx_options.rom.Oaddress->set (strtoul (¶ms[2][8], NULL, 10)); - } - else if (!strcmp(params[0], "optromimage1")) { - if (num_params != 3) { - PARSE_ERR(("%s: optromimage1 directive: wrong # args.", context)); - } - if (strncmp(params[1], "file=", 5)) { - PARSE_ERR(("%s: optromimage1 directive malformed.", context)); - } - if (strncmp(params[2], "address=", 8)) { - PARSE_ERR(("%s: optromimage2 directive malformed.", context)); - } - bx_options.optrom[0].Opath->set (¶ms[1][5]); - if ( (params[2][8] == '0') && (params[2][9] == 'x') ) - bx_options.optrom[0].Oaddress->set (strtoul (¶ms[2][8], NULL, 16)); - else - bx_options.optrom[0].Oaddress->set (strtoul (¶ms[2][8], NULL, 10)); - } - else if (!strcmp(params[0], "optromimage2")) { - if (num_params != 3) { - PARSE_ERR(("%s: optromimage2 directive: wrong # args.", context)); - } - if (strncmp(params[1], "file=", 5)) { - PARSE_ERR(("%s: optromimage2 directive malformed.", context)); - } - if (strncmp(params[2], "address=", 8)) { - PARSE_ERR(("%s: optromimage2 directive malformed.", context)); - } - bx_options.optrom[1].Opath->set (¶ms[1][5]); - if ( (params[2][8] == '0') && (params[2][9] == 'x') ) - bx_options.optrom[1].Oaddress->set (strtoul (¶ms[2][8], NULL, 16)); - else - bx_options.optrom[1].Oaddress->set (strtoul (¶ms[2][8], NULL, 10)); - } - else if (!strcmp(params[0], "optromimage3")) { - if (num_params != 3) { - PARSE_ERR(("%s: optromimage3 directive: wrong # args.", context)); - } - if (strncmp(params[1], "file=", 5)) { - PARSE_ERR(("%s: optromimage3 directive malformed.", context)); - } - if (strncmp(params[2], "address=", 8)) { - PARSE_ERR(("%s: optromimage2 directive malformed.", context)); - } - bx_options.optrom[2].Opath->set (¶ms[1][5]); - if ( (params[2][8] == '0') && (params[2][9] == 'x') ) - bx_options.optrom[2].Oaddress->set (strtoul (¶ms[2][8], NULL, 16)); - else - bx_options.optrom[2].Oaddress->set (strtoul (¶ms[2][8], NULL, 10)); - } - else if (!strcmp(params[0], "optromimage4")) { - if (num_params != 3) { - PARSE_ERR(("%s: optromimage4 directive: wrong # args.", context)); - } - if (strncmp(params[1], "file=", 5)) { - PARSE_ERR(("%s: optromimage4 directive malformed.", context)); - } - if (strncmp(params[2], "address=", 8)) { - PARSE_ERR(("%s: optromimage2 directive malformed.", context)); - } - bx_options.optrom[3].Opath->set (¶ms[1][5]); - if ( (params[2][8] == '0') && (params[2][9] == 'x') ) - bx_options.optrom[3].Oaddress->set (strtoul (¶ms[2][8], NULL, 16)); - else - bx_options.optrom[3].Oaddress->set (strtoul (¶ms[2][8], NULL, 10)); - } - else if (!strcmp(params[0], "vgaromimage")) { - if (num_params != 2) { - PARSE_ERR(("%s: vgaromimage directive: wrong # args.", context)); - } - bx_options.vgarom.Opath->set (params[1]); - } - else if (!strcmp(params[0], "vga_update_interval")) { - if (num_params != 2) { - PARSE_ERR(("%s: vga_update_interval directive: wrong # args.", context)); - } - bx_options.Ovga_update_interval->set (atol(params[1])); - if (bx_options.Ovga_update_interval->get () < 50000) { - BX_INFO(("%s: vga_update_interval seems awfully small!", context)); - } - } - else if (!strcmp(params[0], "keyboard_serial_delay")) { - if (num_params != 2) { - PARSE_ERR(("%s: keyboard_serial_delay directive: wrong # args.", context)); - } - bx_options.Okeyboard_serial_delay->set (atol(params[1])); - if (bx_options.Okeyboard_serial_delay->get () < 5) { - PARSE_ERR (("%s: keyboard_serial_delay not big enough!", context)); - } - } - else if (!strcmp(params[0], "keyboard_paste_delay")) { - if (num_params != 2) { - PARSE_ERR(("%s: keyboard_paste_delay directive: wrong # args.", context)); - } - bx_options.Okeyboard_paste_delay->set (atol(params[1])); - if (bx_options.Okeyboard_paste_delay->get () < 1000) { - PARSE_ERR (("%s: keyboard_paste_delay not big enough!", context)); - } - } - else if (!strcmp(params[0], "megs")) { - if (num_params != 2) { - PARSE_ERR(("%s: megs directive: wrong # args.", context)); - } - bx_options.memory.Osize->set (atol(params[1])); - } - else if (!strcmp(params[0], "floppy_command_delay")) { - if (num_params != 2) { - PARSE_ERR(("%s: floppy_command_delay directive: wrong # args.", context)); - } - bx_options.Ofloppy_command_delay->set (atol(params[1])); - if (bx_options.Ofloppy_command_delay->get () < 100) { - PARSE_ERR(("%s: floppy_command_delay not big enough!", context)); - } - } - else if (!strcmp(params[0], "ips")) { - if (num_params != 2) { - PARSE_ERR(("%s: ips directive: wrong # args.", context)); - } - bx_options.Oips->set (atol(params[1])); - if (bx_options.Oips->get () < BX_MIN_IPS) { - BX_ERROR(("%s: WARNING: ips is AWFULLY low!", context)); - } - } - else if (!strcmp(params[0], "pit")) { // Deprecated - if (num_params != 2) { - PARSE_ERR(("%s: pit directive: wrong # args.", context)); - } - BX_INFO(("WARNING: pit directive is deprecated, use clock: instead")); - if (!strncmp(params[1], "realtime=", 9)) { - switch (params[1][9]) { - case '0': - BX_INFO(("WARNING: not disabling realtime pit")); - break; - case '1': bx_options.clock.Osync->set (BX_CLOCK_SYNC_REALTIME); break; - default: PARSE_ERR(("%s: pit expected realtime=[0|1] arg", context)); - } - } - else PARSE_ERR(("%s: pit expected realtime=[0|1] arg", context)); - } - else if (!strcmp(params[0], "max_ips")) { - if (num_params != 2) { - PARSE_ERR(("%s: max_ips directive: wrong # args.", context)); - } - BX_INFO(("WARNING: max_ips not implemented")); - } - else if (!strcmp(params[0], "text_snapshot_check")) { - if (num_params != 2) { - PARSE_ERR(("%s: text_snapshot_check directive: wrong # args.", context)); - } - if (!strncmp(params[1], "enable", 6)) { - bx_options.Otext_snapshot_check->set (1); - } - else if (!strncmp(params[1], "disable", 7)) { - bx_options.Otext_snapshot_check->set (0); - } - else bx_options.Otext_snapshot_check->set (!!(atol(params[1]))); - } - else if (!strcmp(params[0], "mouse")) { - if (num_params != 2) { - PARSE_ERR(("%s: mouse directive malformed.", context)); - } - if (strncmp(params[1], "enabled=", 8)) { - PARSE_ERR(("%s: mouse directive malformed.", context)); - } - if (params[1][8] == '0' || params[1][8] == '1') - bx_options.Omouse_enabled->set (params[1][8] - '0'); - else - PARSE_ERR(("%s: mouse directive malformed.", context)); - } - else if (!strcmp(params[0], "private_colormap")) { - if (num_params != 2) { - PARSE_ERR(("%s: private_colormap directive malformed.", context)); - } - if (strncmp(params[1], "enabled=", 8)) { - PARSE_ERR(("%s: private_colormap directive malformed.", context)); - } - if (params[1][8] == '0' || params[1][8] == '1') - bx_options.Oprivate_colormap->set (params[1][8] - '0'); - else { - PARSE_ERR(("%s: private_colormap directive malformed.", context)); - } - } - else if (!strcmp(params[0], "fullscreen")) { -#if BX_WITH_AMIGAOS - if (num_params != 2) { - PARSE_ERR(("%s: fullscreen directive malformed.", context)); - } - if (strncmp(params[1], "enabled=", 8)) { - PARSE_ERR(("%s: fullscreen directive malformed.", context)); - } - if (params[1][8] == '0' || params[1][8] == '1') { - bx_options.Ofullscreen->set (params[1][8] - '0'); - } else { - PARSE_ERR(("%s: fullscreen directive malformed.", context)); - } -#endif - } - else if (!strcmp(params[0], "screenmode")) { -#if BX_WITH_AMIGAOS - if (num_params != 2) { - PARSE_ERR(("%s: screenmode directive malformed.", context)); - } - if (strncmp(params[1], "name=", 5)) { - PARSE_ERR(("%s: screenmode directive malformed.", context)); - } - bx_options.Oscreenmode->set (strdup(¶ms[1][5])); -#endif - } - - else if (!strcmp(params[0], "sb16")) { - for (i=1; iset (0); - else if (params[1][8] == '1') - bx_options.Oi440FXSupport->set (1); - else { - PARSE_ERR(("%s: i440FXSupport directive malformed.", context)); - } - } - else if (!strcmp(params[0], "newharddrivesupport")) { - if (num_params != 2) { - PARSE_ERR(("%s: newharddrivesupport directive malformed.", context)); - } - if (strncmp(params[1], "enabled=", 8)) { - PARSE_ERR(("%s: newharddrivesupport directive malformed.", context)); - } - if (params[1][8] == '0') - bx_options.OnewHardDriveSupport->set (0); - else if (params[1][8] == '1') - bx_options.OnewHardDriveSupport->set (1); - else { - PARSE_ERR(("%s: newharddrivesupport directive malformed.", context)); - } - } - else if (!strcmp(params[0], "cmosimage")) { - if (num_params != 2) { - PARSE_ERR(("%s: cmosimage directive: wrong # args.", context)); - } - bx_options.cmos.Opath->set (strdup(params[1])); - bx_options.cmos.OcmosImage->set (1); // CMOS Image is true - } - else if (!strcmp(params[0], "time0")) { // Deprectated - BX_INFO(("WARNING: time0 directive is deprecated, use clock: instead")); - if (num_params != 2) { - PARSE_ERR(("%s: time0 directive: wrong # args.", context)); - } - bx_options.clock.Otime0->set (atoi(params[1])); - } - else if (!strcmp(params[0], "clock")) { - for (i=1; iset (BX_CLOCK_TIME0_LOCAL); - } - else if (!strcmp(params[i], "time0=utc")) { - bx_options.clock.Otime0->set (BX_CLOCK_TIME0_UTC); - } - else if (!strncmp(params[i], "time0=", 6)) { - bx_options.clock.Otime0->set (atoi(¶ms[i][6])); - } - else { - BX_ERROR(("%s: unknown parameter for clock ignored.", context)); - } - } - } -#ifdef MAGIC_BREAKPOINT - else if (!strcmp(params[0], "magic_break")) { - if (num_params != 2) { - PARSE_ERR(("%s: magic_break directive: wrong # args.", context)); - } - if (strncmp(params[1], "enabled=", 8)) { - PARSE_ERR(("%s: magic_break directive malformed.", context)); - } - if (params[1][8] == '0') { - BX_INFO(("Ignoring magic break points")); - bx_dbg.magic_break_enabled = 0; - } - else if (params[1][8] == '1') { - BX_INFO(("Stopping on magic break points")); - bx_dbg.magic_break_enabled = 1; - } - else { - PARSE_ERR(("%s: magic_break directive malformed.", context)); - } - } -#endif - else if (!strcmp(params[0], "ne2k")) { - int tmp[6]; - char tmpchar[6]; - int valid = 0; - int n; - if (!bx_options.ne2k.Opresent->get ()) { - bx_options.ne2k.Oethmod->set_by_name ("null"); - } - for (i=1; iset (tmpchar); - valid |= 0x04; - } - else if (!strncmp(params[i], "ethmod=", 7)) { - if (!bx_options.ne2k.Oethmod->set_by_name (strdup(¶ms[i][7]))) - PARSE_ERR(("%s: ethernet module '%s' not available", context, strdup(¶ms[i][7]))); - } - else if (!strncmp(params[i], "ethdev=", 7)) { - bx_options.ne2k.Oethdev->set (strdup(¶ms[i][7])); - } - else if (!strncmp(params[i], "script=", 7)) { - bx_options.ne2k.Oscript->set (strdup(¶ms[i][7])); - } - else { - PARSE_ERR(("%s: ne2k directive malformed.", context)); - } - } - if (!bx_options.ne2k.Opresent->get ()) { - if (valid == 0x07) { - bx_options.ne2k.Opresent->set (1); - } - else { - PARSE_ERR(("%s: ne2k directive incomplete (ioaddr, irq and mac are required)", context)); - } - } - } - - else if (!strcmp(params[0], "load32bitOSImage")) { - if ( (num_params!=4) && (num_params!=5) ) { - PARSE_ERR(("%s: load32bitOSImage directive: wrong # args.", context)); - } - if (strncmp(params[1], "os=", 3)) { - PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context)); - } - if (!strcmp(¶ms[1][3], "nullkernel")) { - bx_options.load32bitOSImage.OwhichOS->set (Load32bitOSNullKernel); - } - else if (!strcmp(¶ms[1][3], "linux")) { - bx_options.load32bitOSImage.OwhichOS->set (Load32bitOSLinux); - } - else { - PARSE_ERR(("%s: load32bitOSImage: unsupported OS.", context)); - } - if (strncmp(params[2], "path=", 5)) { - PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context)); - } - if (strncmp(params[3], "iolog=", 6)) { - PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context)); - } - bx_options.load32bitOSImage.Opath->set (strdup(¶ms[2][5])); - bx_options.load32bitOSImage.Oiolog->set (strdup(¶ms[3][6])); - if (num_params == 5) { - if (strncmp(params[4], "initrd=", 7)) { - PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context)); - } - bx_options.load32bitOSImage.Oinitrd->set (strdup(¶ms[4][7])); - } - } - else if (!strcmp(params[0], "keyboard_type")) { - if (num_params != 2) { - PARSE_ERR(("%s: keyboard_type directive: wrong # args.", context)); - } - if(strcmp(params[1],"xt")==0){ - bx_options.Okeyboard_type->set (BX_KBD_XT_TYPE); - } - else if(strcmp(params[1],"at")==0){ - bx_options.Okeyboard_type->set (BX_KBD_AT_TYPE); - } - else if(strcmp(params[1],"mf")==0){ - bx_options.Okeyboard_type->set (BX_KBD_MF_TYPE); - } - else{ - PARSE_ERR(("%s: keyboard_type directive: wrong arg %s.", context,params[1])); - } - } - - else if (!strcmp(params[0], "keyboard_mapping") - ||!strcmp(params[0], "keyboardmapping")) { - for (i=1; iset_by_name (params[1])) - PARSE_ERR(("%s: config_interface '%s' not available", context, params[1])); - } - else if (!strcmp(params[0], "display_library")) { - if (num_params != 2) { - PARSE_ERR(("%s: display_library directive: wrong # args.", context)); - } - if (!bx_options.Osel_displaylib->set_by_name (params[1])) - PARSE_ERR(("%s: display library '%s' not available", context, params[1])); - } - else { - PARSE_ERR(( "%s: directive '%s' not understood", context, params[0])); - } - return 0; -} - -static char *fdtypes[] = { - "none", "1_2", "1_44", "2_88", "720k", "360k", "160k", "180k", "320k" -}; - - -int -bx_write_floppy_options (FILE *fp, int drive, bx_floppy_options *opt) -{ - BX_ASSERT (drive==0 || drive==1); - if (opt->Otype->get () == BX_FLOPPY_NONE) { - fprintf (fp, "# no floppy%c\n", (char)'a'+drive); - return 0; - } - BX_ASSERT (opt->Otype->get () > BX_FLOPPY_NONE && opt->Otype->get () <= BX_FLOPPY_LAST); - fprintf (fp, "floppy%c: %s=\"%s\", status=%s\n", - (char)'a'+drive, - fdtypes[opt->Otype->get () - BX_FLOPPY_NONE], - opt->Opath->getptr (), - opt->Ostatus->get ()==BX_EJECTED ? "ejected" : "inserted"); - return 0; -} - -int -bx_write_ata_options (FILE *fp, Bit8u channel, bx_ata_options *opt) -{ - fprintf (fp, "ata%d: enabled=%d", channel, opt->Opresent->get()); - - if (opt->Opresent->get()) { - fprintf (fp, ", ioaddr1=0x%x, ioaddr2=0x%x, irq=%d", opt->Oioaddr1->get(), - opt->Oioaddr2->get(), opt->Oirq->get()); - } - - fprintf (fp, "\n"); - return 0; -} - -int -bx_write_atadevice_options (FILE *fp, Bit8u channel, Bit8u drive, bx_atadevice_options *opt) -{ - if (opt->Opresent->get()) { - fprintf (fp, "ata%d-%s: ", channel, drive==0?"master":"slave"); - - if (opt->Otype->get() == BX_ATA_DEVICE_DISK) { - fprintf (fp, "type=disk"); - - switch(opt->Omode->get()) { - case BX_ATA_MODE_FLAT: - fprintf (fp, ", mode=flat"); - break; - case BX_ATA_MODE_CONCAT: - fprintf (fp, ", mode=concat"); - break; - case BX_ATA_MODE_EXTDISKSIM: - fprintf (fp, ", mode=external"); - break; - case BX_ATA_MODE_DLL_HD: - fprintf (fp, ", mode=dll"); - break; - case BX_ATA_MODE_SPARSE: - fprintf (fp, ", mode=sparse"); - break; - case BX_ATA_MODE_VMWARE3: - fprintf (fp, ", mode=vmware3"); - break; -// case BX_ATA_MODE_SPLIT: -// fprintf (fp, ", mode=split"); -// break; - case BX_ATA_MODE_UNDOABLE: - fprintf (fp, ", mode=undoable"); - break; - case BX_ATA_MODE_GROWING: - fprintf (fp, ", mode=growing"); - break; - case BX_ATA_MODE_VOLATILE: - fprintf (fp, ", mode=volatile"); - break; -// case BX_ATA_MODE_Z_UNDOABLE: -// fprintf (fp, ", mode=z-undoable"); -// break; -// case BX_ATA_MODE_Z_VOLATILE: -// fprintf (fp, ", mode=z-volatile"); -// break; - } - - switch(opt->Otranslation->get()) { - case BX_ATA_TRANSLATION_NONE: - fprintf (fp, ", translation=none"); - break; - case BX_ATA_TRANSLATION_LBA: - fprintf (fp, ", translation=lba"); - break; - case BX_ATA_TRANSLATION_LARGE: - fprintf (fp, ", translation=large"); - break; - case BX_ATA_TRANSLATION_RECHS: - fprintf (fp, ", translation=rechs"); - break; - case BX_ATA_TRANSLATION_AUTO: - fprintf (fp, ", translation=auto"); - break; - } - - fprintf (fp, ", path=\"%s\", cylinders=%d, heads=%d, spt=%d", - opt->Opath->getptr(), - opt->Ocylinders->get(), opt->Oheads->get(), opt->Ospt->get()); - - if (opt->Ojournal->getptr() != NULL) - if ( strcmp(opt->Ojournal->getptr(), "") != 0) - fprintf (fp, ", journal=\"%s\"", opt->Ojournal->getptr()); - - } - else if (opt->Otype->get() == BX_ATA_DEVICE_CDROM) { - fprintf (fp, "type=cdrom, path=\"%s\", status=%s", - opt->Opath->getptr(), - opt->Ostatus->get ()==BX_EJECTED ? "ejected" : "inserted"); - } - - switch(opt->Obiosdetect->get()) { - case BX_ATA_BIOSDETECT_NONE: - fprintf (fp, ", biosdetect=none"); - break; - case BX_ATA_BIOSDETECT_CMOS: - fprintf (fp, ", biosdetect=cmos"); - break; - case BX_ATA_BIOSDETECT_AUTO: - fprintf (fp, ", biosdetect=auto"); - break; - } - if (strlen(opt->Omodel->getptr())>0) { - fprintf (fp, ", model=\"%s\"", opt->Omodel->getptr()); - } - - fprintf (fp, "\n"); - } - return 0; -} - -int -bx_write_parport_options (FILE *fp, bx_parport_options *opt, int n) -{ - fprintf (fp, "parport%d: enabled=%d", n, opt->Oenabled->get ()); - if (opt->Oenabled->get ()) { - fprintf (fp, ", file=\"%s\"", opt->Ooutfile->getptr ()); - } - fprintf (fp, "\n"); - return 0; -} - -int -bx_write_serial_options (FILE *fp, bx_serial_options *opt, int n) -{ - fprintf (fp, "com%d: enabled=%d", n, opt->Oenabled->get ()); - if (opt->Oenabled->get ()) { - fprintf (fp, ", dev=\"%s\"", opt->Odev->getptr ()); - } - fprintf (fp, "\n"); - return 0; -} - -int -bx_write_usb_options (FILE *fp, bx_usb_options *opt, int n) -{ - fprintf (fp, "usb%d: enabled=%d", n, opt->Oenabled->get ()); - if (opt->Oenabled->get ()) { - fprintf (fp, ", ioaddr=0x%04x, irq=%d", opt->Oioaddr->get (), - opt->Oirq->get ()); - } - fprintf (fp, "\n"); - return 0; -} - -int -bx_write_sb16_options (FILE *fp, bx_sb16_options *opt) -{ - if (!opt->Opresent->get ()) { - fprintf (fp, "# no sb16\n"); - return 0; - } - fprintf (fp, "sb16: midimode=%d, midi=%s, wavemode=%d, wave=%s, loglevel=%d, log=%s, dmatimer=%d\n", opt->Omidimode->get (), opt->Omidifile->getptr (), opt->Owavemode->get (), opt->Owavefile->getptr (), opt->Ologlevel->get (), opt->Ologfile->getptr (), opt->Odmatimer->get ()); - return 0; -} - -int -bx_write_ne2k_options (FILE *fp, bx_ne2k_options *opt) -{ - if (!opt->Opresent->get ()) { - fprintf (fp, "# no ne2k\n"); - return 0; - } - char *ptr = opt->Omacaddr->getptr (); - fprintf (fp, "ne2k: ioaddr=0x%x, irq=%d, mac=%02x:%02x:%02x:%02x:%02x:%02x, ethmod=%s, ethdev=%s, script=%s\n", - opt->Oioaddr->get (), - opt->Oirq->get (), - (unsigned int)(0xff & ptr[0]), - (unsigned int)(0xff & ptr[1]), - (unsigned int)(0xff & ptr[2]), - (unsigned int)(0xff & ptr[3]), - (unsigned int)(0xff & ptr[4]), - (unsigned int)(0xff & ptr[5]), - opt->Oethmod->get_choice(opt->Oethmod->get()), - opt->Oethdev->getptr (), - opt->Oscript->getptr ()); - return 0; -} - -int -bx_write_loader_options (FILE *fp, bx_load32bitOSImage_t *opt) -{ - if (opt->OwhichOS->get () == 0) { - fprintf (fp, "# no loader\n"); - return 0; - } - BX_ASSERT(opt->OwhichOS->get () == Load32bitOSLinux || opt->OwhichOS->get () == Load32bitOSNullKernel); - fprintf (fp, "load32bitOSImage: os=%s, path=%s, iolog=%s, initrd=%s\n", - (opt->OwhichOS->get () == Load32bitOSLinux) ? "linux" : "nullkernel", - opt->Opath->getptr (), - opt->Oiolog->getptr (), - opt->Oinitrd->getptr ()); - return 0; -} - -int -bx_write_clock_options (FILE *fp, bx_clock_options *opt) -{ - fprintf (fp, "clock: "); - - switch (opt->Osync->get()) { - case BX_CLOCK_SYNC_NONE: - fprintf (fp, "sync=none"); - break; - case BX_CLOCK_SYNC_REALTIME: - fprintf (fp, "sync=realtime"); - break; - case BX_CLOCK_SYNC_SLOWDOWN: - fprintf (fp, "sync=slowdown"); - break; - case BX_CLOCK_SYNC_BOTH: - fprintf (fp, "sync=both"); - break; - default: - BX_PANIC(("Unknown value for sync method")); - } - - switch (opt->Otime0->get()) { - case 0: break; - case BX_CLOCK_TIME0_LOCAL: - fprintf (fp, ", time0=local"); - break; - case BX_CLOCK_TIME0_UTC: - fprintf (fp, ", time0=utc"); - break; - default: - fprintf (fp, ", time0=%u", opt->Otime0->get()); - } - - fprintf (fp, "\n"); - return 0; -} - -int -bx_write_log_options (FILE *fp, bx_log_options *opt) -{ - fprintf (fp, "log: %s\n", opt->Ofilename->getptr ()); - fprintf (fp, "logprefix: %s\n", opt->Oprefix->getptr ()); - fprintf (fp, "debugger_log: %s\n", opt->Odebugger_filename->getptr ()); - fprintf (fp, "panic: action=%s\n", - io->getaction(logfunctions::get_default_action (LOGLEV_PANIC))); - fprintf (fp, "error: action=%s\n", - io->getaction(logfunctions::get_default_action (LOGLEV_ERROR))); - fprintf (fp, "info: action=%s\n", - io->getaction(logfunctions::get_default_action (LOGLEV_INFO))); - fprintf (fp, "debug: action=%s\n", - io->getaction(logfunctions::get_default_action (LOGLEV_DEBUG))); - fprintf (fp, "pass: action=%s\n", - io->getaction(logfunctions::get_default_action (LOGLEV_PASS))); - return 0; -} - -int -bx_write_keyboard_options (FILE *fp, bx_keyboard_options *opt) -{ - fprintf (fp, "keyboard_mapping: enabled=%d, map=%s\n", opt->OuseMapping->get(), opt->Okeymap->getptr()); - return 0; -} - -// return values: -// 0: written ok -// -1: failed -// -2: already exists, and overwrite was off -int -bx_write_configuration (char *rc, int overwrite) -{ - BX_INFO (("write configuration to %s\n", rc)); - // check if it exists. If so, only proceed if overwrite is set. - FILE *fp = fopen (rc, "r"); - if (fp != NULL) { - fclose (fp); - if (!overwrite) return -2; - } - fp = fopen (rc, "w"); - if (fp == NULL) return -1; - // finally it's open and we can start writing. - fprintf (fp, "# configuration file generated by Bochs\n"); - fprintf (fp, "config_interface: %s\n", bx_options.Osel_config->get_choice(bx_options.Osel_config->get())); - fprintf (fp, "display_library: %s\n", bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get())); - fprintf (fp, "megs: %d\n", bx_options.memory.Osize->get ()); - if (strlen (bx_options.rom.Opath->getptr ()) > 0) - fprintf (fp, "romimage: file=%s, address=0x%05x\n", bx_options.rom.Opath->getptr(), (unsigned int)bx_options.rom.Oaddress->get ()); - else - fprintf (fp, "# no romimage\n"); - if (strlen (bx_options.vgarom.Opath->getptr ()) > 0) - fprintf (fp, "vgaromimage: %s\n", bx_options.vgarom.Opath->getptr ()); - else - fprintf (fp, "# no vgaromimage\n"); - int bootdrive = bx_options.Obootdrive->get (); - fprintf (fp, "boot: %s\n", (bootdrive==BX_BOOT_FLOPPYA) ? "floppy" : (bootdrive==BX_BOOT_DISKC) ? "disk" : "cdrom"); - // it would be nice to put this type of function as methods on - // the structs like bx_floppy_options::print or something. - bx_write_floppy_options (fp, 0, &bx_options.floppya); - bx_write_floppy_options (fp, 1, &bx_options.floppyb); - for (Bit8u channel=0; channelgetptr ()) > 0) - fprintf (fp, "optromimage1: file=%s, address=0x%05x\n", bx_options.optrom[0].Opath->getptr(), (unsigned int)bx_options.optrom[0].Oaddress->get ()); - if (strlen (bx_options.optrom[1].Opath->getptr ()) > 0) - fprintf (fp, "optromimage2: file=%s, address=0x%05x\n", bx_options.optrom[1].Opath->getptr(), (unsigned int)bx_options.optrom[1].Oaddress->get ()); - if (strlen (bx_options.optrom[2].Opath->getptr ()) > 0) - fprintf (fp, "optromimage3: file=%s, address=0x%05x\n", bx_options.optrom[2].Opath->getptr(), (unsigned int)bx_options.optrom[2].Oaddress->get ()); - if (strlen (bx_options.optrom[3].Opath->getptr ()) > 0) - fprintf (fp, "optromimage4: file=%s, address=0x%05x\n", bx_options.optrom[3].Opath->getptr(), (unsigned int)bx_options.optrom[3].Oaddress->get ()); - bx_write_parport_options (fp, &bx_options.par[0], 1); - //bx_write_parport_options (fp, &bx_options.par[1], 2); - bx_write_serial_options (fp, &bx_options.com[0], 1); - //bx_write_serial_options (fp, &bx_options.com[1], 2); - //bx_write_serial_options (fp, &bx_options.com[2], 3); - //bx_write_serial_options (fp, &bx_options.com[3], 4); - bx_write_usb_options (fp, &bx_options.usb[0], 1); - bx_write_sb16_options (fp, &bx_options.sb16); - fprintf (fp, "floppy_bootsig_check: disabled=%d\n", bx_options.OfloppySigCheck->get ()); - fprintf (fp, "vga_update_interval: %u\n", bx_options.Ovga_update_interval->get ()); - fprintf (fp, "keyboard_serial_delay: %u\n", bx_options.Okeyboard_serial_delay->get ()); - fprintf (fp, "keyboard_paste_delay: %u\n", bx_options.Okeyboard_paste_delay->get ()); - fprintf (fp, "floppy_command_delay: %u\n", bx_options.Ofloppy_command_delay->get ()); - fprintf (fp, "ips: %u\n", bx_options.Oips->get ()); - fprintf (fp, "text_snapshot_check: %d\n", bx_options.Otext_snapshot_check->get ()); - fprintf (fp, "mouse: enabled=%d\n", bx_options.Omouse_enabled->get ()); - fprintf (fp, "private_colormap: enabled=%d\n", bx_options.Oprivate_colormap->get ()); -#if BX_WITH_AMIGAOS - fprintf (fp, "fullscreen: enabled=%d\n", bx_options.Ofullscreen->get ()); - fprintf (fp, "screenmode: name=\"%s\"\n", bx_options.Oscreenmode->getptr ()); -#endif - fprintf (fp, "i440fxsupport: enabled=%d\n", bx_options.Oi440FXSupport->get ()); - bx_write_clock_options (fp, &bx_options.clock); - bx_write_ne2k_options (fp, &bx_options.ne2k); - fprintf (fp, "newharddrivesupport: enabled=%d\n", bx_options.OnewHardDriveSupport->get ()); - bx_write_loader_options (fp, &bx_options.load32bitOSImage); - bx_write_log_options (fp, &bx_options.log); - bx_write_keyboard_options (fp, &bx_options.keyboard); - fprintf (fp, "keyboard_type: %s\n", bx_options.Okeyboard_type->get ()==BX_KBD_XT_TYPE?"xt": - bx_options.Okeyboard_type->get ()==BX_KBD_AT_TYPE?"at":"mf"); - fprintf (fp, "user_shortcut: keys=%s\n", bx_options.Ouser_shortcut->getptr ()); - if (strlen (bx_options.cmos.Opath->getptr ()) > 0) - fprintf (fp, "cmosimage: %s\n", bx_options.cmos.Opath->getptr()); - else - fprintf (fp, "# no cmosimage\n"); - fclose (fp); - return 0; -} -#endif // #if BX_PROVIDE_MAIN - - void -bx_signal_handler( int signum) -{ - // in a multithreaded environment, a signal such as SIGINT can be sent to all - // threads. This function is only intended to handle signals in the - // simulator thread. It will simply return if called from any other thread. - // Otherwise the BX_PANIC() below can be called in multiple threads at - // once, leading to multiple threads trying to display a dialog box, - // leading to GUI deadlock. - if (!SIM->is_sim_thread ()) { - BX_INFO (("bx_signal_handler: ignored sig %d because it wasn't called from the simulator thread", signum)); - return; - } -#if BX_GUI_SIGHANDLER - if (bx_gui_sighandler) { - // GUI signal handler gets first priority, if the mask says it's wanted - if ((1<get_sighandler_mask ()) { - bx_gui->sighandler (signum); - return; - } - } -#endif - -#if BX_SHOW_IPS - extern unsigned long ips_count; - - if (signum == SIGALRM ) { - BX_INFO(("ips = %lu", ips_count)); - ips_count = 0; -#ifndef __MINGW32__ - signal(SIGALRM, bx_signal_handler); - alarm( 1 ); -#endif - return; - } -#endif - -#if BX_GUI_SIGHANDLER - if (bx_gui_sighandler) { - if ((1<get_sighandler_mask ()) { - bx_gui->sighandler (signum); - return; - } - } -#endif - BX_PANIC(("SIGNAL %u caught", signum)); -} - diff --git a/tools/ioemu/iodev/ne2k.cc b/tools/ioemu/iodev/ne2k.cc deleted file mode 100644 index d6e0ac4966..0000000000 --- a/tools/ioemu/iodev/ne2k.cc +++ /dev/null @@ -1,1608 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: ne2k.cc,v 1.56.2.1 2004/02/02 22:37:22 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// Peter Grehan (grehan@iprg.nokia.com) coded all of this -// NE2000/ether stuff. - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_NE2K_SUPPORT - -//Never completely fill the ne2k ring so that we never -// hit the unclear completely full buffer condition. -#define BX_NE2K_NEVER_FULL_RING (1) - -#define LOG_THIS theNE2kDevice-> - -bx_ne2k_c *theNE2kDevice = NULL; - - int -libne2k_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - theNE2kDevice = new bx_ne2k_c (); - bx_devices.pluginNE2kDevice = theNE2kDevice; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theNE2kDevice, BX_PLUGIN_NE2K); - return(0); // Success -} - - void -libne2k_LTX_plugin_fini(void) -{ -} - -bx_ne2k_c::bx_ne2k_c(void) -{ - put("NE2K"); - settype(NE2KLOG); - s.tx_timer_index = BX_NULL_TIMER_HANDLE; -} - - -bx_ne2k_c::~bx_ne2k_c(void) -{ - // nothing for now -} - -// -// reset - restore state to power-up, cancelling all i/o -// -void -bx_ne2k_c::reset(unsigned type) -{ - BX_DEBUG (("reset")); - // Zero out registers and memory - memset( & BX_NE2K_THIS s.CR, 0, sizeof(BX_NE2K_THIS s.CR) ); - memset( & BX_NE2K_THIS s.ISR, 0, sizeof(BX_NE2K_THIS s.ISR)); - memset( & BX_NE2K_THIS s.IMR, 0, sizeof(BX_NE2K_THIS s.IMR)); - memset( & BX_NE2K_THIS s.DCR, 0, sizeof(BX_NE2K_THIS s.DCR)); - memset( & BX_NE2K_THIS s.TCR, 0, sizeof(BX_NE2K_THIS s.TCR)); - memset( & BX_NE2K_THIS s.TSR, 0, sizeof(BX_NE2K_THIS s.TSR)); - memset( & BX_NE2K_THIS s.RCR, 0, sizeof(BX_NE2K_THIS s.RCR)); - memset( & BX_NE2K_THIS s.RSR, 0, sizeof(BX_NE2K_THIS s.RSR)); - BX_NE2K_THIS s.local_dma = 0; - BX_NE2K_THIS s.page_start = 0; - BX_NE2K_THIS s.page_stop = 0; - BX_NE2K_THIS s.bound_ptr = 0; - BX_NE2K_THIS s.tx_page_start = 0; - BX_NE2K_THIS s.num_coll = 0; - BX_NE2K_THIS s.tx_bytes = 0; - BX_NE2K_THIS s.fifo = 0; - BX_NE2K_THIS s.remote_dma = 0; - BX_NE2K_THIS s.remote_start = 0; - BX_NE2K_THIS s.remote_bytes = 0; - BX_NE2K_THIS s.tallycnt_0 = 0; - BX_NE2K_THIS s.tallycnt_1 = 0; - BX_NE2K_THIS s.tallycnt_2 = 0; - - memset( & BX_NE2K_THIS s.physaddr, 0, sizeof(BX_NE2K_THIS s.physaddr)); - memset( & BX_NE2K_THIS s.mchash, 0, sizeof(BX_NE2K_THIS s.mchash)); - BX_NE2K_THIS s.curr_page = 0; - - BX_NE2K_THIS s.rempkt_ptr = 0; - BX_NE2K_THIS s.localpkt_ptr = 0; - BX_NE2K_THIS s.address_cnt = 0; - - memset( & BX_NE2K_THIS s.mem, 0, sizeof(BX_NE2K_THIS s.mem)); - - // Set power-up conditions - BX_NE2K_THIS s.CR.stop = 1; - BX_NE2K_THIS s.CR.rdma_cmd = 4; - BX_NE2K_THIS s.ISR.reset = 1; - BX_NE2K_THIS s.DCR.longaddr = 1; - DEV_pic_lower_irq(BX_NE2K_THIS s.base_irq); -} - -// -// read_cr/write_cr - utility routines for handling reads/writes to -// the Command Register -// -Bit32u -bx_ne2k_c::read_cr(void) -{ - Bit32u val = - (((BX_NE2K_THIS s.CR.pgsel & 0x03) << 6) | - ((BX_NE2K_THIS s.CR.rdma_cmd & 0x07) << 3) | - (BX_NE2K_THIS s.CR.tx_packet << 2) | - (BX_NE2K_THIS s.CR.start << 1) | - (BX_NE2K_THIS s.CR.stop)); - BX_DEBUG(("read CR returns 0x%08x", val)); - return val; -} - -void -bx_ne2k_c::write_cr(Bit32u value) -{ - BX_DEBUG(("wrote 0x%02x to CR", value)); - - // Validate remote-DMA - if ((value & 0x38) == 0x00) { - BX_DEBUG(("CR write - invalid rDMA value 0")); - value |= 0x20; /* dma_cmd == 4 is a safe default */ - } - - // Check for s/w reset - if (value & 0x01) { - BX_NE2K_THIS s.ISR.reset = 1; - BX_NE2K_THIS s.CR.stop = 1; - } else { - BX_NE2K_THIS s.CR.stop = 0; - } - - BX_NE2K_THIS s.CR.rdma_cmd = (value & 0x38) >> 3; - - // If start command issued, the RST bit in the ISR - // must be cleared - if ((value & 0x02) && !BX_NE2K_THIS s.CR.start) { - BX_NE2K_THIS s.ISR.reset = 0; - } - - BX_NE2K_THIS s.CR.start = ((value & 0x02) == 0x02); - BX_NE2K_THIS s.CR.pgsel = (value & 0xc0) >> 6; - - // Check for send-packet command - if (BX_NE2K_THIS s.CR.rdma_cmd == 3) { - // Set up DMA read from receive ring - BX_NE2K_THIS s.remote_start = BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.bound_ptr * 256; - BX_NE2K_THIS s.remote_bytes = *((Bit16u*) & BX_NE2K_THIS s.mem[BX_NE2K_THIS s.bound_ptr * 256 + 2 - BX_NE2K_MEMSTART]); - BX_INFO(("Sending buffer #x%x length %d", - BX_NE2K_THIS s.remote_start, - BX_NE2K_THIS s.remote_bytes)); - } - - // Check for start-tx - if ((value & 0x04) && BX_NE2K_THIS s.TCR.loop_cntl) { - if (BX_NE2K_THIS s.TCR.loop_cntl != 1) { - BX_INFO(("Loop mode %d not supported.", BX_NE2K_THIS s.TCR.loop_cntl)); - } else { - rx_frame (& BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 - BX_NE2K_MEMSTART], - BX_NE2K_THIS s.tx_bytes); - } - } else if (value & 0x04) { - if (BX_NE2K_THIS s.CR.stop || !BX_NE2K_THIS s.CR.start) - BX_PANIC(("CR write - tx start, dev in reset")); - - if (BX_NE2K_THIS s.tx_bytes == 0) - BX_PANIC(("CR write - tx start, tx bytes == 0")); - -#ifdef notdef - // XXX debug stuff - printf("packet tx (%d bytes):\t", BX_NE2K_THIS s.tx_bytes); - for (int i = 0; i < BX_NE2K_THIS s.tx_bytes; i++) { - printf("%02x ", BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 - - BX_NE2K_MEMSTART + i]); - if (i && (((i+1) % 16) == 0)) - printf("\t"); - } - printf(""); -#endif - - // Send the packet to the system driver - BX_NE2K_THIS ethdev->sendpkt(& BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 - BX_NE2K_MEMSTART], BX_NE2K_THIS s.tx_bytes); - - // some more debug - if (BX_NE2K_THIS s.tx_timer_active) - BX_PANIC(("CR write, tx timer still active")); - - // Schedule a timer to trigger a tx-complete interrupt - // The number of microseconds is the bit-time / 10. - // The bit-time is the preamble+sfd (64 bits), the - // inter-frame gap (96 bits), the CRC (4 bytes), and the - // the number of bits in the frame (s.tx_bytes * 8). - // - bx_pc_system.activate_timer(BX_NE2K_THIS s.tx_timer_index, - (64 + 96 + 4*8 + BX_NE2K_THIS s.tx_bytes*8)/10, - 0); // not continuous - } - - // Linux probes for an interrupt by setting up a remote-DMA read - // of 0 bytes with remote-DMA completion interrupts enabled. - // Detect this here - if (BX_NE2K_THIS s.CR.rdma_cmd == 0x01 && - BX_NE2K_THIS s.CR.start && - BX_NE2K_THIS s.remote_bytes == 0) { - BX_NE2K_THIS s.ISR.rdma_done = 1; - if (BX_NE2K_THIS s.IMR.rdma_inte) { - DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq); - } - } -} - -// -// chipmem_read/chipmem_write - access the 64K private RAM. -// The ne2000 memory is accessed through the data port of -// the asic (offset 0) after setting up a remote-DMA transfer. -// Both byte and word accesses are allowed. -// The first 16 bytes contains the MAC address at even locations, -// and there is 16K of buffer memory starting at 16K -// -Bit32u BX_CPP_AttrRegparmN(2) -bx_ne2k_c::chipmem_read(Bit32u address, unsigned int io_len) -{ - Bit32u retval = 0; - - if ((io_len == 2) && (address & 0x1)) - BX_PANIC(("unaligned chipmem word read")); - - // ROM'd MAC address - if ((address >=0) && (address <= 31)) { - retval = BX_NE2K_THIS s.macaddr[address]; - if (io_len == 2) { - retval |= (BX_NE2K_THIS s.macaddr[address + 1] << 8); - } - return (retval); - } - - if ((address >= BX_NE2K_MEMSTART) && (address < BX_NE2K_MEMEND)) { - retval = BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART]; - if (io_len == 2) { - retval |= (BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART + 1] << 8); - } - return (retval); - } - - BX_DEBUG(("out-of-bounds chipmem read, %04X", address)); - - return (0xff); -} - -void BX_CPP_AttrRegparmN(3) -bx_ne2k_c::chipmem_write(Bit32u address, Bit32u value, unsigned io_len) -{ - if ((io_len == 2) && (address & 0x1)) - BX_PANIC(("unaligned chipmem word write")); - - if ((address >= BX_NE2K_MEMSTART) && (address < BX_NE2K_MEMEND)) { - BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART] = value & 0xff; - if (io_len == 2) - BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART + 1] = value >> 8; - } else - BX_DEBUG(("out-of-bounds chipmem write, %04X", address)); -} - -// -// asic_read/asic_write - This is the high 16 bytes of i/o space -// (the lower 16 bytes is for the DS8390). Only two locations -// are used: offset 0, which is used for data transfer, and -// offset 0xf, which is used to reset the device. -// The data transfer port is used to as 'external' DMA to the -// DS8390. The chip has to have the DMA registers set up, and -// after that, insw/outsw instructions can be used to move -// the appropriate number of bytes to/from the device. -// -Bit32u BX_CPP_AttrRegparmN(2) -bx_ne2k_c::asic_read(Bit32u offset, unsigned int io_len) -{ - Bit32u retval = 0; - - switch (offset) { - case 0x0: // Data register - // - // A read remote-DMA command must have been issued, - // and the source-address and length registers must - // have been initialised. - // - if (io_len > BX_NE2K_THIS s.remote_bytes) - { - BX_ERROR(("ne2K: dma read underrun iolen=%d remote_bytes=%d",io_len,BX_NE2K_THIS s.remote_bytes)); - //return 0; - } - - //BX_INFO(("ne2k read DMA: addr=%4x remote_bytes=%d",BX_NE2K_THIS s.remote_dma,BX_NE2K_THIS s.remote_bytes)); - retval = chipmem_read(BX_NE2K_THIS s.remote_dma, io_len); - // - // The 8390 bumps the address and decreases the byte count - // by the selected word size after every access, not by - // the amount of data requested by the host (io_len). - // - BX_NE2K_THIS s.remote_dma += (BX_NE2K_THIS s.DCR.wdsize + 1); - if (BX_NE2K_THIS s.remote_dma == BX_NE2K_THIS s.page_stop << 8) { - BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.page_start << 8; - } - // keep s.remote_bytes from underflowing - if (BX_NE2K_THIS s.remote_bytes > 1) - BX_NE2K_THIS s.remote_bytes -= (BX_NE2K_THIS s.DCR.wdsize + 1); - else - BX_NE2K_THIS s.remote_bytes = 0; - - // If all bytes have been written, signal remote-DMA complete - if (BX_NE2K_THIS s.remote_bytes == 0) { - BX_NE2K_THIS s.ISR.rdma_done = 1; - if (BX_NE2K_THIS s.IMR.rdma_inte) { - DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq); - } - } - break; - - case 0xf: // Reset register - theNE2kDevice->reset(BX_RESET_SOFTWARE); - break; - - default: - BX_INFO(("asic read invalid address %04x", (unsigned) offset)); - break; - } - - return (retval); -} - -void -bx_ne2k_c::asic_write(Bit32u offset, Bit32u value, unsigned io_len) -{ - BX_DEBUG(("asic write addr=0x%02x, value=0x%04x", (unsigned) offset, (unsigned) value)); - switch (offset) { - case 0x0: // Data register - see asic_read for a description - - if ((io_len == 2) && (BX_NE2K_THIS s.DCR.wdsize == 0)) { - BX_PANIC(("dma write length 2 on byte mode operation")); - break; - } - - if (BX_NE2K_THIS s.remote_bytes == 0) - BX_PANIC(("ne2K: dma write, byte count 0")); - - chipmem_write(BX_NE2K_THIS s.remote_dma, value, io_len); - // is this right ??? asic_read uses DCR.wordsize - BX_NE2K_THIS s.remote_dma += io_len; - if (BX_NE2K_THIS s.remote_dma == BX_NE2K_THIS s.page_stop << 8) { - BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.page_start << 8; - } - - BX_NE2K_THIS s.remote_bytes -= io_len; - if (BX_NE2K_THIS s.remote_bytes > BX_NE2K_MEMSIZ) - BX_NE2K_THIS s.remote_bytes = 0; - - // If all bytes have been written, signal remote-DMA complete - if (BX_NE2K_THIS s.remote_bytes == 0) { - BX_NE2K_THIS s.ISR.rdma_done = 1; - if (BX_NE2K_THIS s.IMR.rdma_inte) { - DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq); - } - } - break; - - case 0xf: // Reset register - theNE2kDevice->reset(BX_RESET_SOFTWARE); - break; - - default: // this is invalid, but happens under win95 device detection - BX_INFO(("asic write invalid address %04x, ignoring", (unsigned) offset)); - break ; - } -} - -// -// page0_read/page0_write - These routines handle reads/writes to -// the 'zeroth' page of the DS8390 register file -// -Bit32u -bx_ne2k_c::page0_read(Bit32u offset, unsigned int io_len) -{ - BX_DEBUG(("page 0 read from port %04x, len=%u", (unsigned) offset, - (unsigned) io_len)); - if (io_len > 1) { - BX_ERROR(("bad length! page 0 read from port %04x, len=%u", (unsigned) offset, - (unsigned) io_len)); /* encountered with win98 hardware probe */ - return 0; - } - - - switch (offset) { - case 0x0: // CR - return (read_cr()); - break; - - case 0x1: // CLDA0 - return (BX_NE2K_THIS s.local_dma & 0xff); - break; - - case 0x2: // CLDA1 - return (BX_NE2K_THIS s.local_dma >> 8); - break; - - case 0x3: // BNRY - return (BX_NE2K_THIS s.bound_ptr); - break; - - case 0x4: // TSR - return ((BX_NE2K_THIS s.TSR.ow_coll << 7) | - (BX_NE2K_THIS s.TSR.cd_hbeat << 6) | - (BX_NE2K_THIS s.TSR.fifo_ur << 5) | - (BX_NE2K_THIS s.TSR.no_carrier << 4) | - (BX_NE2K_THIS s.TSR.aborted << 3) | - (BX_NE2K_THIS s.TSR.collided << 2) | - (BX_NE2K_THIS s.TSR.tx_ok)); - break; - - case 0x5: // NCR - return (BX_NE2K_THIS s.num_coll); - break; - - case 0x6: // FIFO - // reading FIFO is only valid in loopback mode - BX_ERROR(("reading FIFO not supported yet")); - return (BX_NE2K_THIS s.fifo); - break; - - case 0x7: // ISR - return ((BX_NE2K_THIS s.ISR.reset << 7) | - (BX_NE2K_THIS s.ISR.rdma_done << 6) | - (BX_NE2K_THIS s.ISR.cnt_oflow << 5) | - (BX_NE2K_THIS s.ISR.overwrite << 4) | - (BX_NE2K_THIS s.ISR.tx_err << 3) | - (BX_NE2K_THIS s.ISR.rx_err << 2) | - (BX_NE2K_THIS s.ISR.pkt_tx << 1) | - (BX_NE2K_THIS s.ISR.pkt_rx)); - break; - - case 0x8: // CRDA0 - return (BX_NE2K_THIS s.remote_dma & 0xff); - break; - - case 0x9: // CRDA1 - return (BX_NE2K_THIS s.remote_dma >> 8); - break; - - case 0xa: // reserved - BX_INFO(("reserved read - page 0, 0xa")); - return (0xff); - break; - - case 0xb: // reserved - BX_INFO(("reserved read - page 0, 0xb")); - return (0xff); - break; - - case 0xc: // RSR - return ((BX_NE2K_THIS s.RSR.deferred << 7) | - (BX_NE2K_THIS s.RSR.rx_disabled << 6) | - (BX_NE2K_THIS s.RSR.rx_mbit << 5) | - (BX_NE2K_THIS s.RSR.rx_missed << 4) | - (BX_NE2K_THIS s.RSR.fifo_or << 3) | - (BX_NE2K_THIS s.RSR.bad_falign << 2) | - (BX_NE2K_THIS s.RSR.bad_crc << 1) | - (BX_NE2K_THIS s.RSR.rx_ok)); - break; - - case 0xd: // CNTR0 - return (BX_NE2K_THIS s.tallycnt_0); - break; - - case 0xe: // CNTR1 - return (BX_NE2K_THIS s.tallycnt_1); - break; - - case 0xf: // CNTR2 - return (BX_NE2K_THIS s.tallycnt_2); - break; - - default: - BX_PANIC(("page 0 offset %04x out of range", (unsigned) offset)); - } - - return(0); -} - -void -bx_ne2k_c::page0_write(Bit32u offset, Bit32u value, unsigned io_len) -{ - BX_DEBUG(("page 0 write to port %04x, len=%u", (unsigned) offset, - (unsigned) io_len)); - - // It appears to be a common practice to use outw on page0 regs... - - // break up outw into two outb's - if (io_len == 2) { - page0_write(offset, (value & 0xff), 1); - page0_write(offset + 1, ((value >> 8) & 0xff), 1); - return; - } - - switch (offset) { - case 0x0: // CR - write_cr(value); - break; - - case 0x1: // PSTART - BX_NE2K_THIS s.page_start = value; - break; - - case 0x2: // PSTOP - // BX_INFO(("Writing to PSTOP: %02x", value)); - BX_NE2K_THIS s.page_stop = value; - break; - - case 0x3: // BNRY - BX_NE2K_THIS s.bound_ptr = value; - break; - - case 0x4: // TPSR - BX_NE2K_THIS s.tx_page_start = value; - break; - - case 0x5: // TBCR0 - // Clear out low byte and re-insert - BX_NE2K_THIS s.tx_bytes &= 0xff00; - BX_NE2K_THIS s.tx_bytes |= (value & 0xff); - break; - - case 0x6: // TBCR1 - // Clear out high byte and re-insert - BX_NE2K_THIS s.tx_bytes &= 0x00ff; - BX_NE2K_THIS s.tx_bytes |= ((value & 0xff) << 8); - break; - - case 0x7: // ISR - value &= 0x7f; // clear RST bit - status-only bit - // All other values are cleared iff the ISR bit is 1 - BX_NE2K_THIS s.ISR.pkt_rx &= ~((bx_bool)((value & 0x01) == 0x01)); - BX_NE2K_THIS s.ISR.pkt_tx &= ~((bx_bool)((value & 0x02) == 0x02)); - BX_NE2K_THIS s.ISR.rx_err &= ~((bx_bool)((value & 0x04) == 0x04)); - BX_NE2K_THIS s.ISR.tx_err &= ~((bx_bool)((value & 0x08) == 0x08)); - BX_NE2K_THIS s.ISR.overwrite &= ~((bx_bool)((value & 0x10) == 0x10)); - BX_NE2K_THIS s.ISR.cnt_oflow &= ~((bx_bool)((value & 0x20) == 0x20)); - BX_NE2K_THIS s.ISR.rdma_done &= ~((bx_bool)((value & 0x40) == 0x40)); - value = ((BX_NE2K_THIS s.ISR.rdma_done << 6) | - (BX_NE2K_THIS s.ISR.cnt_oflow << 5) | - (BX_NE2K_THIS s.ISR.overwrite << 4) | - (BX_NE2K_THIS s.ISR.tx_err << 3) | - (BX_NE2K_THIS s.ISR.rx_err << 2) | - (BX_NE2K_THIS s.ISR.pkt_tx << 1) | - (BX_NE2K_THIS s.ISR.pkt_rx)); - value &= ((BX_NE2K_THIS s.IMR.rdma_inte << 6) | - (BX_NE2K_THIS s.IMR.cofl_inte << 5) | - (BX_NE2K_THIS s.IMR.overw_inte << 4) | - (BX_NE2K_THIS s.IMR.txerr_inte << 3) | - (BX_NE2K_THIS s.IMR.rxerr_inte << 2) | - (BX_NE2K_THIS s.IMR.tx_inte << 1) | - (BX_NE2K_THIS s.IMR.rx_inte)); - if (value == 0) - DEV_pic_lower_irq(BX_NE2K_THIS s.base_irq); - break; - - case 0x8: // RSAR0 - // Clear out low byte and re-insert - BX_NE2K_THIS s.remote_start &= 0xff00; - BX_NE2K_THIS s.remote_start |= (value & 0xff); - BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.remote_start; - break; - - case 0x9: // RSAR1 - // Clear out high byte and re-insert - BX_NE2K_THIS s.remote_start &= 0x00ff; - BX_NE2K_THIS s.remote_start |= ((value & 0xff) << 8); - BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.remote_start; - break; - - case 0xa: // RBCR0 - // Clear out low byte and re-insert - BX_NE2K_THIS s.remote_bytes &= 0xff00; - BX_NE2K_THIS s.remote_bytes |= (value & 0xff); - break; - - case 0xb: // RBCR1 - // Clear out high byte and re-insert - BX_NE2K_THIS s.remote_bytes &= 0x00ff; - BX_NE2K_THIS s.remote_bytes |= ((value & 0xff) << 8); - break; - - case 0xc: // RCR - // Check if the reserved bits are set - if (value & 0xc0) - BX_INFO(("RCR write, reserved bits set")); - - // Set all other bit-fields - BX_NE2K_THIS s.RCR.errors_ok = ((value & 0x01) == 0x01); - BX_NE2K_THIS s.RCR.runts_ok = ((value & 0x02) == 0x02); - BX_NE2K_THIS s.RCR.broadcast = ((value & 0x04) == 0x04); - BX_NE2K_THIS s.RCR.multicast = ((value & 0x08) == 0x08); - BX_NE2K_THIS s.RCR.promisc = ((value & 0x10) == 0x10); - BX_NE2K_THIS s.RCR.monitor = ((value & 0x20) == 0x20); - - // Monitor bit is a little suspicious... - if (value & 0x20) - BX_INFO(("RCR write, monitor bit set!")); - break; - - case 0xd: // TCR - // Check reserved bits - if (value & 0xe0) - BX_ERROR(("TCR write, reserved bits set")); - - // Test loop mode (not supported) - if (value & 0x06) { - BX_NE2K_THIS s.TCR.loop_cntl = (value & 0x6) >> 1; - BX_INFO(("TCR write, loop mode %d not supported", BX_NE2K_THIS s.TCR.loop_cntl)); - } else { - BX_NE2K_THIS s.TCR.loop_cntl = 0; - } - - // Inhibit-CRC not supported. - if (value & 0x01) - BX_PANIC(("TCR write, inhibit-CRC not supported")); - - // Auto-transmit disable very suspicious - if (value & 0x08) - BX_PANIC(("TCR write, auto transmit disable not supported")); - - // Allow collision-offset to be set, although not used - BX_NE2K_THIS s.TCR.coll_prio = ((value & 0x08) == 0x08); - break; - - case 0xe: // DCR - // the loopback mode is not suppported yet - if (!(value & 0x08)) { - BX_ERROR(("DCR write, loopback mode selected")); - } - // It is questionable to set longaddr and auto_rx, since they - // aren't supported on the ne2000. Print a warning and continue - if (value & 0x04) - BX_INFO(("DCR write - LAS set ???")); - if (value & 0x10) - BX_INFO(("DCR write - AR set ???")); - - // Set other values. - BX_NE2K_THIS s.DCR.wdsize = ((value & 0x01) == 0x01); - BX_NE2K_THIS s.DCR.endian = ((value & 0x02) == 0x02); - BX_NE2K_THIS s.DCR.longaddr = ((value & 0x04) == 0x04); // illegal ? - BX_NE2K_THIS s.DCR.loop = ((value & 0x08) == 0x08); - BX_NE2K_THIS s.DCR.auto_rx = ((value & 0x10) == 0x10); // also illegal ? - BX_NE2K_THIS s.DCR.fifo_size = (value & 0x50) >> 5; - break; - - case 0xf: // IMR - // Check for reserved bit - if (value & 0x80) - BX_PANIC(("IMR write, reserved bit set")); - - // Set other values - BX_NE2K_THIS s.IMR.rx_inte = ((value & 0x01) == 0x01); - BX_NE2K_THIS s.IMR.tx_inte = ((value & 0x02) == 0x02); - BX_NE2K_THIS s.IMR.rxerr_inte = ((value & 0x04) == 0x04); - BX_NE2K_THIS s.IMR.txerr_inte = ((value & 0x08) == 0x08); - BX_NE2K_THIS s.IMR.overw_inte = ((value & 0x10) == 0x10); - BX_NE2K_THIS s.IMR.cofl_inte = ((value & 0x20) == 0x20); - BX_NE2K_THIS s.IMR.rdma_inte = ((value & 0x40) == 0x40); - break; - - default: - BX_PANIC(("page 0 write, bad offset %0x", offset)); - } -} - - -// -// page1_read/page1_write - These routines handle reads/writes to -// the first page of the DS8390 register file -// -Bit32u -bx_ne2k_c::page1_read(Bit32u offset, unsigned int io_len) -{ - BX_DEBUG(("page 1 read from port %04x, len=%u", (unsigned) offset, - (unsigned) io_len)); - if (io_len > 1) - BX_PANIC(("bad length! page 1 read from port %04x, len=%u", (unsigned) offset, - (unsigned) io_len)); - - switch (offset) { - case 0x0: // CR - return (read_cr()); - break; - - case 0x1: // PAR0-5 - case 0x2: - case 0x3: - case 0x4: - case 0x5: - case 0x6: - return (BX_NE2K_THIS s.physaddr[offset - 1]); - break; - - case 0x7: // CURR - BX_DEBUG(("returning current page: %02x", (BX_NE2K_THIS s.curr_page))); - return (BX_NE2K_THIS s.curr_page); - - case 0x8: // MAR0-7 - case 0x9: - case 0xa: - case 0xb: - case 0xc: - case 0xd: - case 0xe: - case 0xf: - return (BX_NE2K_THIS s.mchash[offset - 8]); - break; - - default: - BX_PANIC(("page 1 r offset %04x out of range", (unsigned) offset)); - } - - return (0); -} - -void -bx_ne2k_c::page1_write(Bit32u offset, Bit32u value, unsigned io_len) -{ - BX_DEBUG(("page 1 w offset %04x", (unsigned) offset)); - switch (offset) { - case 0x0: // CR - write_cr(value); - break; - - case 0x1: // PAR0-5 - case 0x2: - case 0x3: - case 0x4: - case 0x5: - case 0x6: - BX_NE2K_THIS s.physaddr[offset - 1] = value; - break; - - case 0x7: // CURR - BX_NE2K_THIS s.curr_page = value; - break; - - case 0x8: // MAR0-7 - case 0x9: - case 0xa: - case 0xb: - case 0xc: - case 0xd: - case 0xe: - case 0xf: - BX_NE2K_THIS s.mchash[offset - 8] = value; - break; - - default: - BX_PANIC(("page 1 w offset %04x out of range", (unsigned) offset)); - } -} - - -// -// page2_read/page2_write - These routines handle reads/writes to -// the second page of the DS8390 register file -// -Bit32u -bx_ne2k_c::page2_read(Bit32u offset, unsigned int io_len) -{ - BX_DEBUG(("page 2 read from port %04x, len=%u", (unsigned) offset, (unsigned) io_len)); - - if (io_len > 1) - BX_PANIC(("bad length! page 2 read from port %04x, len=%u", (unsigned) offset, (unsigned) io_len)); - - switch (offset) { - case 0x0: // CR - return (read_cr()); - break; - - case 0x1: // PSTART - return (BX_NE2K_THIS s.page_start); - break; - - case 0x2: // PSTOP - return (BX_NE2K_THIS s.page_stop); - break; - - case 0x3: // Remote Next-packet pointer - return (BX_NE2K_THIS s.rempkt_ptr); - break; - - case 0x4: // TPSR - return (BX_NE2K_THIS s.tx_page_start); - break; - - case 0x5: // Local Next-packet pointer - return (BX_NE2K_THIS s.localpkt_ptr); - break; - - case 0x6: // Address counter (upper) - return (BX_NE2K_THIS s.address_cnt >> 8); - break; - - case 0x7: // Address counter (lower) - return (BX_NE2K_THIS s.address_cnt & 0xff); - break; - - case 0x8: // Reserved - case 0x9: - case 0xa: - case 0xb: - BX_ERROR(("reserved read - page 2, 0x%02x", (unsigned) offset)); - return (0xff); - break; - - case 0xc: // RCR - return ((BX_NE2K_THIS s.RCR.monitor << 5) | - (BX_NE2K_THIS s.RCR.promisc << 4) | - (BX_NE2K_THIS s.RCR.multicast << 3) | - (BX_NE2K_THIS s.RCR.broadcast << 2) | - (BX_NE2K_THIS s.RCR.runts_ok << 1) | - (BX_NE2K_THIS s.RCR.errors_ok)); - break; - - case 0xd: // TCR - return ((BX_NE2K_THIS s.TCR.coll_prio << 4) | - (BX_NE2K_THIS s.TCR.ext_stoptx << 3) | - ((BX_NE2K_THIS s.TCR.loop_cntl & 0x3) << 1) | - (BX_NE2K_THIS s.TCR.crc_disable)); - break; - - case 0xe: // DCR - return (((BX_NE2K_THIS s.DCR.fifo_size & 0x3) << 5) | - (BX_NE2K_THIS s.DCR.auto_rx << 4) | - (BX_NE2K_THIS s.DCR.loop << 3) | - (BX_NE2K_THIS s.DCR.longaddr << 2) | - (BX_NE2K_THIS s.DCR.endian << 1) | - (BX_NE2K_THIS s.DCR.wdsize)); - break; - - case 0xf: // IMR - return ((BX_NE2K_THIS s.IMR.rdma_inte << 6) | - (BX_NE2K_THIS s.IMR.cofl_inte << 5) | - (BX_NE2K_THIS s.IMR.overw_inte << 4) | - (BX_NE2K_THIS s.IMR.txerr_inte << 3) | - (BX_NE2K_THIS s.IMR.rxerr_inte << 2) | - (BX_NE2K_THIS s.IMR.tx_inte << 1) | - (BX_NE2K_THIS s.IMR.rx_inte)); - break; - - default: - BX_PANIC(("page 2 offset %04x out of range", (unsigned) offset)); - } - - return (0); -}; - -void -bx_ne2k_c::page2_write(Bit32u offset, Bit32u value, unsigned io_len) -{ - // Maybe all writes here should be BX_PANIC()'d, since they - // affect internal operation, but let them through for now - // and print a warning. - if (offset != 0) - BX_ERROR(("page 2 write ?")); - - switch (offset) { - case 0x0: // CR - write_cr(value); - break; - - case 0x1: // CLDA0 - // Clear out low byte and re-insert - BX_NE2K_THIS s.local_dma &= 0xff00; - BX_NE2K_THIS s.local_dma |= (value & 0xff); - break; - - case 0x2: // CLDA1 - // Clear out high byte and re-insert - BX_NE2K_THIS s.local_dma &= 0x00ff; - BX_NE2K_THIS s.local_dma |= ((value & 0xff) << 8); - break; - - case 0x3: // Remote Next-pkt pointer - BX_NE2K_THIS s.rempkt_ptr = value; - break; - - case 0x4: - BX_PANIC(("page 2 write to reserved offset 4")); - break; - - case 0x5: // Local Next-packet pointer - BX_NE2K_THIS s.localpkt_ptr = value; - break; - - case 0x6: // Address counter (upper) - // Clear out high byte and re-insert - BX_NE2K_THIS s.address_cnt &= 0x00ff; - BX_NE2K_THIS s.address_cnt |= ((value & 0xff) << 8); - break; - - case 0x7: // Address counter (lower) - // Clear out low byte and re-insert - BX_NE2K_THIS s.address_cnt &= 0xff00; - BX_NE2K_THIS s.address_cnt |= (value & 0xff); - break; - - case 0x8: - case 0x9: - case 0xa: - case 0xb: - case 0xc: - case 0xd: - case 0xe: - case 0xf: - BX_PANIC(("page 2 write to reserved offset %0x", offset)); - break; - - default: - BX_PANIC(("page 2 write, illegal offset %0x", offset)); - break; - } -} - -// -// page3_read/page3_write - writes to this page are illegal -// -Bit32u -bx_ne2k_c::page3_read(Bit32u offset, unsigned int io_len) -{ - BX_PANIC(("page 3 read attempted")); - return (0); -} - -void -bx_ne2k_c::page3_write(Bit32u offset, Bit32u value, unsigned io_len) -{ - BX_PANIC(("page 3 write attempted")); -} - -// -// tx_timer_handler/tx_timer -// -void -bx_ne2k_c::tx_timer_handler(void *this_ptr) -{ - bx_ne2k_c *class_ptr = (bx_ne2k_c *) this_ptr; - - class_ptr->tx_timer(); -} - -void -bx_ne2k_c::tx_timer(void) -{ - BX_DEBUG(("tx_timer")); - BX_NE2K_THIS s.TSR.tx_ok = 1; - // Generate an interrupt if not masked and not one in progress - if (BX_NE2K_THIS s.IMR.tx_inte && !BX_NE2K_THIS s.ISR.pkt_tx) { - BX_NE2K_THIS s.ISR.pkt_tx = 1; - DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq); - } - BX_NE2K_THIS s.tx_timer_active = 0; -} - - -// -// read_handler/read - i/o 'catcher' function called from BOCHS -// mainline when the CPU attempts a read in the i/o space registered -// by this ne2000 instance -// -Bit32u -bx_ne2k_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_NE2K_SMF - bx_ne2k_c *class_ptr = (bx_ne2k_c *) this_ptr; - - return( class_ptr->read(address, io_len) ); -} - -Bit32u -bx_ne2k_c::read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_NE2K_SMF - BX_DEBUG(("read addr %x, len %d", address, io_len)); - Bit32u retval = 0; - int offset = address - BX_NE2K_THIS s.base_address; - - if (offset >= 0x10) { - retval = asic_read(offset - 0x10, io_len); - } else { - switch (BX_NE2K_THIS s.CR.pgsel) { - case 0x00: - retval = page0_read(offset, io_len); - break; - - case 0x01: - retval = page1_read(offset, io_len); - break; - - case 0x02: - retval = page2_read(offset, io_len); - break; - - case 0x03: - retval = page3_read(offset, io_len); - break; - - default: - BX_PANIC(("ne2K: unknown value of pgsel in read - %d", - BX_NE2K_THIS s.CR.pgsel)); - } - } - - return (retval); -} - -// -// write_handler/write - i/o 'catcher' function called from BOCHS -// mainline when the CPU attempts a write in the i/o space registered -// by this ne2000 instance -// -void -bx_ne2k_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, - unsigned io_len) -{ -#if !BX_USE_NE2K_SMF - bx_ne2k_c *class_ptr = (bx_ne2k_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - -void -bx_ne2k_c::write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_NE2K_SMF - BX_DEBUG(("write with length %d", io_len)); - int offset = address - BX_NE2K_THIS s.base_address; - - // - // The high 16 bytes of i/o space are for the ne2000 asic - - // the low 16 bytes are for the DS8390, with the current - // page being selected by the PS0,PS1 registers in the - // command register - // - if (offset >= 0x10) { - asic_write(offset - 0x10, value, io_len); - } else { - switch (BX_NE2K_THIS s.CR.pgsel) { - case 0x00: - page0_write(offset, value, io_len); - break; - - case 0x01: - page1_write(offset, value, io_len); - break; - - case 0x02: - page2_write(offset, value, io_len); - break; - - case 0x03: - page3_write(offset, value, io_len); - break; - - default: - BX_PANIC(("ne2K: unknown value of pgsel in write - %d", - BX_NE2K_THIS s.CR.pgsel)); - } - } -} - - -/* - * mcast_index() - return the 6-bit index into the multicast - * table. Stolen unashamedly from FreeBSD's if_ed.c - */ -unsigned -bx_ne2k_c::mcast_index(const void *dst) -{ -#define POLYNOMIAL 0x04c11db6 - unsigned long crc = 0xffffffffL; - int carry, i, j; - unsigned char b; - unsigned char *ep = (unsigned char *) dst; - - for (i = 6; --i >= 0;) { - b = *ep++; - for (j = 8; --j >= 0;) { - carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); - crc <<= 1; - b >>= 1; - if (carry) - crc = ((crc ^ POLYNOMIAL) | carry); - } - } - return (crc >> 26); -#undef POLYNOMIAL -} - -/* - * Callback from the eth system driver when a frame has arrived - */ -void -bx_ne2k_c::rx_handler(void *arg, const void *buf, unsigned len) -{ - // BX_DEBUG(("rx_handler with length %d", len)); - bx_ne2k_c *class_ptr = (bx_ne2k_c *) arg; - - class_ptr->rx_frame(buf, len); -} - -/* - * rx_frame() - called by the platform-specific code when an - * ethernet frame has been received. The destination address - * is tested to see if it should be accepted, and if the - * rx ring has enough room, it is copied into it and - * the receive process is updated - */ -void -bx_ne2k_c::rx_frame(const void *buf, unsigned io_len) -{ - unsigned pages; - unsigned avail; - unsigned idx; - int wrapped; - int nextpage; - unsigned char pkthdr[4]; - unsigned char *pktbuf = (unsigned char *) buf; - unsigned char *startptr; - static unsigned char bcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; - - BX_DEBUG(("rx_frame with length %d", io_len)); - - - if ((BX_NE2K_THIS s.CR.stop != 0) || - (BX_NE2K_THIS s.page_start == 0) || - ((BX_NE2K_THIS s.DCR.loop == 0) && - (BX_NE2K_THIS s.TCR.loop_cntl != 0))) { - - return; - } - - // Add the pkt header + CRC to the length, and work - // out how many 256-byte pages the frame would occupy - pages = (io_len + 4 + 4 + 255)/256; - - if (BX_NE2K_THIS s.curr_page < BX_NE2K_THIS s.bound_ptr) { - avail = BX_NE2K_THIS s.bound_ptr - BX_NE2K_THIS s.curr_page; - } else { - avail = (BX_NE2K_THIS s.page_stop - BX_NE2K_THIS s.page_start) - - (BX_NE2K_THIS s.curr_page - BX_NE2K_THIS s.bound_ptr); - wrapped = 1; - } - - // Avoid getting into a buffer overflow condition by not attempting - // to do partial receives. The emulation to handle this condition - // seems particularly painful. - if ((avail < pages) -#if BX_NE2K_NEVER_FULL_RING - || (avail == pages) -#endif - ) { - return; - } - - if ((io_len < 60) && !BX_NE2K_THIS s.RCR.runts_ok) { - BX_DEBUG(("rejected small packet, length %d", io_len)); - return; - } - - // Do address filtering if not in promiscuous mode - if (! BX_NE2K_THIS s.RCR.promisc) { - if (!memcmp(buf, bcast_addr, 6)) { - if (!BX_NE2K_THIS s.RCR.broadcast) { - return; - } - } else if (pktbuf[0] & 0x01) { - if (! BX_NE2K_THIS s.RCR.multicast) { - return; - } - idx = mcast_index(buf); - if (!(BX_NE2K_THIS s.mchash[idx >> 3] & (1 << (idx & 0x7)))) { - return; - } - } else if (0 != memcmp(buf, BX_NE2K_THIS s.physaddr, 6)) { - return; - } - } else { - BX_DEBUG(("rx_frame promiscuous receive")); - } - -// BX_INFO(("rx_frame %d to %x:%x:%x:%x:%x:%x from %x:%x:%x:%x:%x:%x", -// io_len, -// pktbuf[0], pktbuf[1], pktbuf[2], pktbuf[3], pktbuf[4], pktbuf[5], -// pktbuf[6], pktbuf[7], pktbuf[8], pktbuf[9], pktbuf[10], pktbuf[11])); - - nextpage = BX_NE2K_THIS s.curr_page + pages; - if (nextpage >= BX_NE2K_THIS s.page_stop) { - nextpage -= BX_NE2K_THIS s.page_stop - BX_NE2K_THIS s.page_start; - } - - // Setup packet header - pkthdr[0] = 0; // rx status - old behavior - pkthdr[0] = 1; // Probably better to set it all the time - // rather than set it to 0, which is clearly wrong. - if (pktbuf[0] & 0x01) { - pkthdr[0] |= 0x20; // rx status += multicast packet - } - pkthdr[1] = nextpage; // ptr to next packet - pkthdr[2] = (io_len + 4) & 0xff; // length-low - pkthdr[3] = (io_len + 4) >> 8; // length-hi - - // copy into buffer, update curpage, and signal interrupt if config'd - startptr = & BX_NE2K_THIS s.mem[BX_NE2K_THIS s.curr_page * 256 - - BX_NE2K_MEMSTART]; - if ((nextpage > BX_NE2K_THIS s.curr_page) || - ((BX_NE2K_THIS s.curr_page + pages) == BX_NE2K_THIS s.page_stop)) { - memcpy(startptr, pkthdr, 4); - memcpy(startptr + 4, buf, io_len); - BX_NE2K_THIS s.curr_page = nextpage; - } else { - int endbytes = (BX_NE2K_THIS s.page_stop - BX_NE2K_THIS s.curr_page) - * 256; - memcpy(startptr, pkthdr, 4); - memcpy(startptr + 4, buf, endbytes - 4); - startptr = & BX_NE2K_THIS s.mem[BX_NE2K_THIS s.page_start * 256 - - BX_NE2K_MEMSTART]; - memcpy(startptr, (void *)(pktbuf + endbytes - 4), - io_len - endbytes + 8); - BX_NE2K_THIS s.curr_page = nextpage; - } - - BX_NE2K_THIS s.RSR.rx_ok = 1; - if (pktbuf[0] & 0x80) { - BX_NE2K_THIS s.RSR.rx_mbit = 1; - } - - BX_NE2K_THIS s.ISR.pkt_rx = 1; - - if (BX_NE2K_THIS s.IMR.rx_inte) { - DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq); - } - -} - -void -bx_ne2k_c::init(void) -{ - BX_DEBUG(("Init $Id: ne2k.cc,v 1.56.2.1 2004/02/02 22:37:22 cbothamy Exp $")); - - // Read in values from config file - BX_NE2K_THIS s.base_address = bx_options.ne2k.Oioaddr->get (); - BX_NE2K_THIS s.base_irq = bx_options.ne2k.Oirq->get (); - memcpy(BX_NE2K_THIS s.physaddr, bx_options.ne2k.Omacaddr->getptr (), 6); - - if (BX_NE2K_THIS s.tx_timer_index == BX_NULL_TIMER_HANDLE) { - BX_NE2K_THIS s.tx_timer_index = - bx_pc_system.register_timer(this, tx_timer_handler, 0, - 0,0, "ne2k"); // one-shot, inactive - } - // Register the IRQ and i/o port addresses - DEV_register_irq(BX_NE2K_THIS s.base_irq, "NE2000 ethernet NIC"); - - for (unsigned addr = BX_NE2K_THIS s.base_address; - addr <= BX_NE2K_THIS s.base_address + 0x20; - addr++) { - DEV_register_ioread_handler(this, read_handler, addr, "ne2000 NIC", 3); - DEV_register_iowrite_handler(this, write_handler, addr, "ne2000 NIC", 3); - } - BX_INFO(("port 0x%x/32 irq %d mac %02x:%02x:%02x:%02x:%02x:%02x", - BX_NE2K_THIS s.base_address, - BX_NE2K_THIS s.base_irq, - BX_NE2K_THIS s.physaddr[0], - BX_NE2K_THIS s.physaddr[1], - BX_NE2K_THIS s.physaddr[2], - BX_NE2K_THIS s.physaddr[3], - BX_NE2K_THIS s.physaddr[4], - BX_NE2K_THIS s.physaddr[5])); - - // Initialise the mac address area by doubling the physical address - BX_NE2K_THIS s.macaddr[0] = BX_NE2K_THIS s.physaddr[0]; - BX_NE2K_THIS s.macaddr[1] = BX_NE2K_THIS s.physaddr[0]; - BX_NE2K_THIS s.macaddr[2] = BX_NE2K_THIS s.physaddr[1]; - BX_NE2K_THIS s.macaddr[3] = BX_NE2K_THIS s.physaddr[1]; - BX_NE2K_THIS s.macaddr[4] = BX_NE2K_THIS s.physaddr[2]; - BX_NE2K_THIS s.macaddr[5] = BX_NE2K_THIS s.physaddr[2]; - BX_NE2K_THIS s.macaddr[6] = BX_NE2K_THIS s.physaddr[3]; - BX_NE2K_THIS s.macaddr[7] = BX_NE2K_THIS s.physaddr[3]; - BX_NE2K_THIS s.macaddr[8] = BX_NE2K_THIS s.physaddr[4]; - BX_NE2K_THIS s.macaddr[9] = BX_NE2K_THIS s.physaddr[4]; - BX_NE2K_THIS s.macaddr[10] = BX_NE2K_THIS s.physaddr[5]; - BX_NE2K_THIS s.macaddr[11] = BX_NE2K_THIS s.physaddr[5]; - - // ne2k signature - for (int i = 12; i < 32; i++) - BX_NE2K_THIS s.macaddr[i] = 0x57; - - // Attach to the simulated ethernet dev - char *ethmod = bx_options.ne2k.Oethmod->get_choice(bx_options.ne2k.Oethmod->get()); - BX_NE2K_THIS ethdev = eth_locator_c::create(ethmod, - bx_options.ne2k.Oethdev->getptr (), - (const char *) bx_options.ne2k.Omacaddr->getptr (), - rx_handler, - this); - - if (BX_NE2K_THIS ethdev == NULL) { - BX_PANIC(("could not find eth module %s", ethmod)); - // if they continue, use null. - BX_INFO(("could not find eth module %s - using null instead", ethmod)); - - BX_NE2K_THIS ethdev = eth_locator_c::create("null", NULL, - (const char *) bx_options.ne2k.Omacaddr->getptr (), - rx_handler, - this); - if (BX_NE2K_THIS ethdev == NULL) - BX_PANIC(("could not locate null module")); - } - - // Bring the register state into power-up state - theNE2kDevice->reset(BX_RESET_HARDWARE); -} - -#if BX_DEBUGGER - -/* - * this implements the info ne2k commands in the debugger. - * info ne2k - shows all registers - * info ne2k page N - shows all registers in a page - * info ne2k page N reg M - shows just one register - */ - -#define SHOW_FIELD(reg,field) do { \ - if (n>0 && !(n%5)) dbg_printf ("\n "); \ - dbg_printf ("%s=%d ", #field, BX_NE2K_THIS s.reg.field); \ - n++; \ -} while (0); -#define BX_HIGH_BYTE(x) ((0xff00 & (x)) >> 8) -#define BX_LOW_BYTE(x) (0x00ff & (x)) -#define BX_DUPLICATE(n) if (brief && num!=n) break; - -void -bx_ne2k_c::print_info (FILE *fp, int page, int reg, int brief) -{ - int i; - int n = 0; - if (page < 0) { - for (page=0; page<=2; page++) - theNE2kDevice->print_info (fp, page, reg, 1); - // tell them how to use this command - dbg_printf ("\nHow to use the info ne2k command:\n"); - dbg_printf ("info ne2k - show all registers\n"); - dbg_printf ("info ne2k page N - show registers in page N\n"); - dbg_printf ("info ne2k page N reg M - show just one register\n"); - return; - } - if (page > 2) { - dbg_printf ("NE2K has only pages 0, 1, and 2. Page %d is out of range.\n", page); - return; - } - if (reg < 0) { - dbg_printf ("NE2K registers, page %d\n", page); - dbg_printf ("----------------------\n"); - for (reg=0; reg<=15; reg++) - theNE2kDevice->print_info (fp, page, reg, 1); - dbg_printf ("----------------------\n"); - return; - } - if (reg > 15) { - dbg_printf ("NE2K has only registers 0-15 (0x0-0xf). Register %d is out of range.\n", reg); - return; - } - if (!brief) { - dbg_printf ("NE2K Info - page %d, register 0x%02x\n", page, reg); - dbg_printf ("----------------------------------\n"); - } - int num = page*0x100 + reg; - switch (num) { - case 0x0000: - case 0x0100: - case 0x0200: - dbg_printf ("CR (Command register):\n "); - SHOW_FIELD (CR, stop); - SHOW_FIELD (CR, start); - SHOW_FIELD (CR, tx_packet); - SHOW_FIELD (CR, rdma_cmd); - SHOW_FIELD (CR, pgsel); - dbg_printf ("\n"); - break; - case 0x0003: - dbg_printf ("BNRY = Boundary Pointer = 0x%02x\n", BX_NE2K_THIS s.bound_ptr); - break; - case 0x0004: - dbg_printf ("TSR (Transmit Status Register), read-only:\n "); - SHOW_FIELD (TSR, tx_ok); - SHOW_FIELD (TSR, reserved); - SHOW_FIELD (TSR, collided); - SHOW_FIELD (TSR, aborted); - SHOW_FIELD (TSR, no_carrier); - SHOW_FIELD (TSR, fifo_ur); - SHOW_FIELD (TSR, cd_hbeat); - SHOW_FIELD (TSR, ow_coll); - dbg_printf ("\n"); - // fall through into TPSR, no break line. - case 0x0204: - dbg_printf ("TPSR = Transmit Page Start = 0x%02x\n", BX_NE2K_THIS s.tx_page_start); - break; - case 0x0005: - case 0x0006: BX_DUPLICATE(0x0005); - dbg_printf ("NCR = Number of Collisions Register (read-only) = 0x%02x\n", BX_NE2K_THIS s.num_coll); - dbg_printf ("TBCR1,TBCR0 = Transmit Byte Count = %02x %02x\n", - BX_HIGH_BYTE (BX_NE2K_THIS s.tx_bytes), - BX_LOW_BYTE (BX_NE2K_THIS s.tx_bytes)); - dbg_printf ("FIFO = %02x\n", BX_NE2K_THIS s.fifo); - break; - case 0x0007: - dbg_printf ("ISR (Interrupt Status Register):\n "); - SHOW_FIELD (ISR, pkt_rx); - SHOW_FIELD (ISR, pkt_tx); - SHOW_FIELD (ISR, rx_err); - SHOW_FIELD (ISR, tx_err); - SHOW_FIELD (ISR, overwrite); - SHOW_FIELD (ISR, cnt_oflow); - SHOW_FIELD (ISR, rdma_done); - SHOW_FIELD (ISR, reset); - dbg_printf ("\n"); - break; - case 0x0008: - case 0x0009: BX_DUPLICATE(0x0008); - dbg_printf ("CRDA1,0 = Current remote DMA address = %02x %02x\n", - BX_HIGH_BYTE (BX_NE2K_THIS s.remote_dma), - BX_LOW_BYTE (BX_NE2K_THIS s.remote_dma)); - dbg_printf ("RSAR1,0 = Remote start address = %02x %02x\n", - BX_HIGH_BYTE(s.remote_start), - BX_LOW_BYTE(s.remote_start)); - break; - case 0x000a: - case 0x000b: BX_DUPLICATE(0x000a); - dbg_printf ("RCBR1,0 = Remote byte count = %02x\n", BX_NE2K_THIS s.remote_bytes); - break; - case 0x000c: - dbg_printf ("RSR (Receive Status Register), read-only:\n "); - SHOW_FIELD (RSR, rx_ok); - SHOW_FIELD (RSR, bad_crc); - SHOW_FIELD (RSR, bad_falign); - SHOW_FIELD (RSR, fifo_or); - SHOW_FIELD (RSR, rx_missed); - SHOW_FIELD (RSR, rx_mbit); - SHOW_FIELD (RSR, rx_disabled); - SHOW_FIELD (RSR, deferred); - dbg_printf ("\n"); - // fall through into RCR - case 0x020c: - dbg_printf ("RCR (Receive Configuration Register):\n "); - SHOW_FIELD (RCR, errors_ok); - SHOW_FIELD (RCR, runts_ok); - SHOW_FIELD (RCR, broadcast); - SHOW_FIELD (RCR, multicast); - SHOW_FIELD (RCR, promisc); - SHOW_FIELD (RCR, monitor); - SHOW_FIELD (RCR, reserved); - dbg_printf ("\n"); - break; - case 0x000d: - dbg_printf ("CNTR0 = Tally Counter 0 (Frame alignment errors) = %02x\n", - BX_NE2K_THIS s.tallycnt_0); - // fall through into TCR - case 0x020d: - dbg_printf ("TCR (Transmit Configuration Register):\n "); - SHOW_FIELD (TCR, crc_disable); - SHOW_FIELD (TCR, loop_cntl); - SHOW_FIELD (TCR, ext_stoptx); - SHOW_FIELD (TCR, coll_prio); - SHOW_FIELD (TCR, reserved); - dbg_printf ("\n"); - break; - case 0x000e: - dbg_printf ("CNTR1 = Tally Counter 1 (CRC Errors) = %02x\n", - BX_NE2K_THIS s.tallycnt_1); - // fall through into DCR - case 0x020e: - dbg_printf ("DCR (Data Configuration Register):\n "); - SHOW_FIELD (DCR, wdsize); - SHOW_FIELD (DCR, endian); - SHOW_FIELD (DCR, longaddr); - SHOW_FIELD (DCR, loop); - SHOW_FIELD (DCR, auto_rx); - SHOW_FIELD (DCR, fifo_size); - dbg_printf ("\n"); - break; - case 0x000f: - dbg_printf ("CNTR2 = Tally Counter 2 (Missed Packet Errors) = %02x\n", - BX_NE2K_THIS s.tallycnt_2); - // fall through into IMR - case 0x020f: - dbg_printf ("IMR (Interrupt Mask Register)\n "); - SHOW_FIELD (IMR, rx_inte); - SHOW_FIELD (IMR, tx_inte); - SHOW_FIELD (IMR, rxerr_inte); - SHOW_FIELD (IMR, txerr_inte); - SHOW_FIELD (IMR, overw_inte); - SHOW_FIELD (IMR, cofl_inte); - SHOW_FIELD (IMR, rdma_inte); - SHOW_FIELD (IMR, reserved); - dbg_printf ("\n"); - break; - case 0x0101: - case 0x0102: BX_DUPLICATE(0x0101); - case 0x0103: BX_DUPLICATE(0x0101); - case 0x0104: BX_DUPLICATE(0x0101); - case 0x0105: BX_DUPLICATE(0x0101); - case 0x0106: BX_DUPLICATE(0x0101); - dbg_printf ("MAC address registers are located at page 1, registers 1-6.\n"); - dbg_printf ("The MAC address is "); - for (i=0; i<=5; i++) - dbg_printf ("%02x%c", BX_NE2K_THIS s.physaddr[i], i<5?':' : '\n'); - break; - case 0x0107: - dbg_printf ("Current page is 0x%02x\n", BX_NE2K_THIS s.curr_page); - break; - case 0x0108: - case 0x0109: BX_DUPLICATE(0x0108); - case 0x010A: BX_DUPLICATE(0x0108); - case 0x010B: BX_DUPLICATE(0x0108); - case 0x010C: BX_DUPLICATE(0x0108); - case 0x010D: BX_DUPLICATE(0x0108); - case 0x010E: BX_DUPLICATE(0x0108); - case 0x010F: BX_DUPLICATE(0x0108); - dbg_printf ("MAR0-7 (Multicast address registers 0-7) are set to:\n"); - for (i=0; i<8; i++) dbg_printf ("%02x ", BX_NE2K_THIS s.mchash[i]); - dbg_printf ("\nMAR0 is listed first.\n"); - break; - case 0x0001: - case 0x0002: BX_DUPLICATE(0x0001); - case 0x0201: BX_DUPLICATE(0x0001); - case 0x0202: BX_DUPLICATE(0x0001); - dbg_printf ("PSTART = Page start register = %02x\n", BX_NE2K_THIS s.page_start); - dbg_printf ("PSTOP = Page stop register = %02x\n", BX_NE2K_THIS s.page_stop); - dbg_printf ("Local DMA address = %02x %02x\n", - BX_HIGH_BYTE(BX_NE2K_THIS s.local_dma), - BX_LOW_BYTE(BX_NE2K_THIS s.local_dma)); - break; - case 0x0203: - dbg_printf ("Remote Next Packet Pointer = %02x\n", BX_NE2K_THIS s.rempkt_ptr); - break; - case 0x0205: - dbg_printf ("Local Next Packet Pointer = %02x\n", BX_NE2K_THIS s.localpkt_ptr); - break; - case 0x0206: - case 0x0207: BX_DUPLICATE(0x0206); - dbg_printf ("Address Counter= %02x %02x\n", - BX_HIGH_BYTE(BX_NE2K_THIS s.address_cnt), - BX_LOW_BYTE(BX_NE2K_THIS s.address_cnt)); - break; - case 0x0208: - case 0x0209: BX_DUPLICATE(0x0208); - case 0x020A: BX_DUPLICATE(0x0208); - case 0x020B: BX_DUPLICATE(0x0208); - if (!brief) dbg_printf ("Reserved\n"); - case 0xffff: - dbg_printf ("IMR (Interrupt Mask Register):\n "); - dbg_printf ("\n"); - break; - default: - dbg_printf ("NE2K info: sorry, page %d register %d cannot be displayed.\n", page, reg); - } - if (!brief) - dbg_printf ("\n"); -} - -#else - -void -bx_ne2k_c::print_info (FILE *fp, int page, int reg, int brief) -{ -} - -#endif - -#endif /* if BX_NE2K_SUPPORT */ diff --git a/tools/ioemu/iodev/ne2k.h b/tools/ioemu/iodev/ne2k.h deleted file mode 100644 index 37cc712106..0000000000 --- a/tools/ioemu/iodev/ne2k.h +++ /dev/null @@ -1,239 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: ne2k.h,v 1.11 2003/03/02 23:59:11 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// Peter Grehan (grehan@iprg.nokia.com) coded all of this -// NE2000/ether stuff. - -// -// An implementation of an ne2000 ISA ethernet adapter. This part uses -// a National Semiconductor DS-8390 ethernet MAC chip, with some h/w -// to provide a windowed memory region for the chip and a MAC address. -// - - -#if BX_USE_NE2K_SMF -# define BX_NE2K_SMF static -# define BX_NE2K_THIS theNE2kDevice-> -#else -# define BX_NE2K_SMF -# define BX_NE2K_THIS this-> -#endif - -#define BX_NE2K_MEMSIZ (32*1024) -#define BX_NE2K_MEMSTART (16*1024) -#define BX_NE2K_MEMEND (BX_NE2K_MEMSTART + BX_NE2K_MEMSIZ) - -typedef struct { - // - // ne2k register state - - // - // Page 0 - // - // Command Register - 00h read/write - struct { - bx_bool stop; // STP - Software Reset command - bx_bool start; // START - start the NIC - bx_bool tx_packet; // TXP - initiate packet transmission - Bit8u rdma_cmd; // RD0,RD1,RD2 - Remote DMA command - Bit8u pgsel; // PS0,PS1 - Page select - } CR; - // Interrupt Status Register - 07h read/write - struct { - bx_bool pkt_rx; // PRX - packet received with no errors - bx_bool pkt_tx; // PTX - packet transmitted with no errors - bx_bool rx_err; // RXE - packet received with 1 or more errors - bx_bool tx_err; // TXE - packet tx'd " " " " " - bx_bool overwrite; // OVW - rx buffer resources exhausted - bx_bool cnt_oflow; // CNT - network tally counter MSB's set - bx_bool rdma_done; // RDC - remote DMA complete - bx_bool reset; // RST - reset status - } ISR; - // Interrupt Mask Register - 0fh write - struct { - bx_bool rx_inte; // PRXE - packet rx interrupt enable - bx_bool tx_inte; // PTXE - packet tx interrput enable - bx_bool rxerr_inte; // RXEE - rx error interrupt enable - bx_bool txerr_inte; // TXEE - tx error interrupt enable - bx_bool overw_inte; // OVWE - overwrite warn int enable - bx_bool cofl_inte; // CNTE - counter o'flow int enable - bx_bool rdma_inte; // RDCE - remote DMA complete int enable - bx_bool reserved; // D7 - reserved - } IMR; - // Data Configuration Register - 0eh write - struct { - bx_bool wdsize; // WTS - 8/16-bit select - bx_bool endian; // BOS - byte-order select - bx_bool longaddr; // LAS - long-address select - bx_bool loop; // LS - loopback select - bx_bool auto_rx; // AR - auto-remove rx packets with remote DMA - Bit8u fifo_size; // FT0,FT1 - fifo threshold - } DCR; - // Transmit Configuration Register - 0dh write - struct { - bx_bool crc_disable; // CRC - inhibit tx CRC - Bit8u loop_cntl; // LB0,LB1 - loopback control - bx_bool ext_stoptx; // ATD - allow tx disable by external mcast - bx_bool coll_prio; // OFST - backoff algorithm select - Bit8u reserved; // D5,D6,D7 - reserved - } TCR; - // Transmit Status Register - 04h read - struct { - bx_bool tx_ok; // PTX - tx complete without error - bx_bool reserved; // D1 - reserved - bx_bool collided; // COL - tx collided >= 1 times - bx_bool aborted; // ABT - aborted due to excessive collisions - bx_bool no_carrier; // CRS - carrier-sense lost - bx_bool fifo_ur; // FU - FIFO underrun - bx_bool cd_hbeat; // CDH - no tx cd-heartbeat from transceiver - bx_bool ow_coll; // OWC - out-of-window collision - } TSR; - // Receive Configuration Register - 0ch write - struct { - bx_bool errors_ok; // SEP - accept pkts with rx errors - bx_bool runts_ok; // AR - accept < 64-byte runts - bx_bool broadcast; // AB - accept eth broadcast address - bx_bool multicast; // AM - check mcast hash array - bx_bool promisc; // PRO - accept all packets - bx_bool monitor; // MON - check pkts, but don't rx - Bit8u reserved; // D6,D7 - reserved - } RCR; - // Receive Status Register - 0ch read - struct { - bx_bool rx_ok; // PRX - rx complete without error - bx_bool bad_crc; // CRC - Bad CRC detected - bx_bool bad_falign; // FAE - frame alignment error - bx_bool fifo_or; // FO - FIFO overrun - bx_bool rx_missed; // MPA - missed packet error - bx_bool rx_mbit; // PHY - unicast or mcast/bcast address match - bx_bool rx_disabled; // DIS - set when in monitor mode - bx_bool deferred; // DFR - collision active - } RSR; - - Bit16u local_dma; // 01,02h read ; current local DMA addr - Bit8u page_start; // 01h write ; page start register - Bit8u page_stop; // 02h write ; page stop register - Bit8u bound_ptr; // 03h read/write ; boundary pointer - Bit8u tx_page_start; // 04h write ; transmit page start register - Bit8u num_coll; // 05h read ; number-of-collisions register - Bit16u tx_bytes; // 05,06h write ; transmit byte-count register - Bit8u fifo; // 06h read ; FIFO - Bit16u remote_dma; // 08,09h read ; current remote DMA addr - Bit16u remote_start; // 08,09h write ; remote start address register - Bit16u remote_bytes; // 0a,0bh write ; remote byte-count register - Bit8u tallycnt_0; // 0dh read ; tally counter 0 (frame align errors) - Bit8u tallycnt_1; // 0eh read ; tally counter 1 (CRC errors) - Bit8u tallycnt_2; // 0fh read ; tally counter 2 (missed pkt errors) - - // - // Page 1 - // - // Command Register 00h (repeated) - // - Bit8u physaddr[6]; // 01-06h read/write ; MAC address - Bit8u curr_page; // 07h read/write ; current page register - Bit8u mchash[8]; // 08-0fh read/write ; multicast hash array - - // - // Page 2 - diagnostic use only - // - // Command Register 00h (repeated) - // - // Page Start Register 01h read (repeated) - // Page Stop Register 02h read (repeated) - // Current Local DMA Address 01,02h write (repeated) - // Transmit Page start address 04h read (repeated) - // Receive Configuration Register 0ch read (repeated) - // Transmit Configuration Register 0dh read (repeated) - // Data Configuration Register 0eh read (repeated) - // Interrupt Mask Register 0fh read (repeated) - // - Bit8u rempkt_ptr; // 03h read/write ; remote next-packet pointer - Bit8u localpkt_ptr; // 05h read/write ; local next-packet pointer - Bit16u address_cnt; // 06,07h read/write ; address counter - - // - // Page 3 - should never be modified. - // - - // Novell ASIC state - Bit8u macaddr[32]; // ASIC ROM'd MAC address, even bytes - Bit8u mem[BX_NE2K_MEMSIZ]; // on-chip packet memory - - // ne2k internal state - Bit32u base_address; - int base_irq; - int tx_timer_index; - int tx_timer_active; - -} bx_ne2k_t; - - - -class bx_ne2k_c : public bx_ne2k_stub_c { -public: - bx_ne2k_c(void); - ~bx_ne2k_c(void); - virtual void init(void); - virtual void reset(unsigned type); - virtual void print_info (FILE *file, int page, int reg, int nodups); - -private: - bx_ne2k_t s; - - eth_pktmover_c *ethdev; - - BX_NE2K_SMF Bit32u read_cr(void); - BX_NE2K_SMF void write_cr(Bit32u value); - - BX_NE2K_SMF Bit32u chipmem_read(Bit32u address, unsigned io_len) BX_CPP_AttrRegparmN(2); - BX_NE2K_SMF Bit32u asic_read(Bit32u offset, unsigned io_len) BX_CPP_AttrRegparmN(2); - BX_NE2K_SMF Bit32u page0_read(Bit32u offset, unsigned io_len); - BX_NE2K_SMF Bit32u page1_read(Bit32u offset, unsigned io_len); - BX_NE2K_SMF Bit32u page2_read(Bit32u offset, unsigned io_len); - BX_NE2K_SMF Bit32u page3_read(Bit32u offset, unsigned io_len); - - BX_NE2K_SMF void chipmem_write(Bit32u address, Bit32u value, unsigned io_len) BX_CPP_AttrRegparmN(3); - BX_NE2K_SMF void asic_write(Bit32u address, Bit32u value, unsigned io_len); - BX_NE2K_SMF void page0_write(Bit32u address, Bit32u value, unsigned io_len); - BX_NE2K_SMF void page1_write(Bit32u address, Bit32u value, unsigned io_len); - BX_NE2K_SMF void page2_write(Bit32u address, Bit32u value, unsigned io_len); - BX_NE2K_SMF void page3_write(Bit32u address, Bit32u value, unsigned io_len); - - static void tx_timer_handler(void *); - BX_NE2K_SMF void tx_timer(void); - - static void rx_handler(void *arg, const void *buf, unsigned len); - BX_NE2K_SMF unsigned mcast_index(const void *dst); - BX_NE2K_SMF void rx_frame(const void *buf, unsigned io_len); - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); -#if !BX_USE_NE2K_SMF - Bit32u read(Bit32u address, unsigned io_len); - void write(Bit32u address, Bit32u value, unsigned io_len); -#endif -}; diff --git a/tools/ioemu/iodev/osdep.cc b/tools/ioemu/iodev/osdep.cc deleted file mode 100644 index c010306c82..0000000000 --- a/tools/ioemu/iodev/osdep.cc +++ /dev/null @@ -1,340 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: osdep.cc,v 1.14.2.1 2004/02/06 22:14:34 danielg4 Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// -// osdep.cc -// -// Provide definition of library functions that are missing on various -// systems. The only reason this is a .cc file rather than a .c file -// is so that it can include bochs.h. Bochs.h includes all the required -// system headers, with appropriate #ifdefs for different compilers and -// platforms. -// - -#include "bochs.h" - -////////////////////////////////////////////////////////////////////// -// Missing library functions. These should work on any platform -// that needs them. -////////////////////////////////////////////////////////////////////// - -#if !BX_HAVE_SNPRINTF -/* XXX use real snprintf */ -/* if they don't have snprintf, just use sprintf */ -int bx_snprintf (char *s, size_t maxlen, const char *format, ...) -{ - va_list arg; - int done; - - va_start (arg, format); - done = vsprintf (s, format, arg); - va_end (arg); - - return done; -} -#endif /* !BX_HAVE_SNPRINTF */ - - -#if (!BX_HAVE_STRTOULL && !BX_HAVE_STRTOUQ) -/* taken from glibc-2.2.2: strtod.c, and stripped down a lot. There are - still a few leftover references to decimal points and exponents, - but it works for bases 10 and 16 */ - -#define RETURN(val,end) \ - do { if (endptr != NULL) *endptr = (char *) (end); \ - return val; } while (0) - -Bit64u -bx_strtoull (const char *nptr, char **endptr, int baseignore) -{ - int negative; /* The sign of the number. */ - int exponent; /* Exponent of the number. */ - - /* Numbers starting `0X' or `0x' have to be processed with base 16. */ - int base = 10; - - /* Number of bits currently in result value. */ - int bits; - - /* Running pointer after the last character processed in the string. */ - const char *cp, *tp; - /* Start of significant part of the number. */ - const char *startp, *start_of_digits; - /* Total number of digit and number of digits in integer part. */ - int dig_no; - /* Contains the last character read. */ - char c; - - Bit64s n = 0; - char const *p; - - /* Prepare number representation. */ - exponent = 0; - negative = 0; - bits = 0; - - /* Parse string to get maximal legal prefix. We need the number of - characters of the integer part, the fractional part and the exponent. */ - cp = nptr - 1; - /* Ignore leading white space. */ - do - c = *++cp; - while (isspace (c)); - - /* Get sign of the result. */ - if (c == '-') - { - negative = 1; - c = *++cp; - } - else if (c == '+') - c = *++cp; - - if (c < '0' || c > '9') - { - /* It is really a text we do not recognize. */ - RETURN (0, nptr); - } - - /* First look whether we are faced with a hexadecimal number. */ - if (c == '0' && tolower (cp[1]) == 'x') - { - /* Okay, it is a hexa-decimal number. Remember this and skip - the characters. BTW: hexadecimal numbers must not be - grouped. */ - base = 16; - cp += 2; - c = *cp; - } - - /* Record the start of the digits, in case we will check their grouping. */ - start_of_digits = startp = cp; - - /* Ignore leading zeroes. This helps us to avoid useless computations. */ - while (c == '0') - c = *++cp; - - /* If no other digit but a '0' is found the result is 0.0. - Return current read pointer. */ - if ((c < '0' || c > '9') - && (base == 16 && (c < tolower ('a') || c > tolower ('f'))) - && (base == 16 && (cp == start_of_digits || tolower (c) != 'p')) - && (base != 16 && tolower (c) != 'e')) - { - tp = start_of_digits; - /* If TP is at the start of the digits, there was no correctly - grouped prefix of the string; so no number found. */ - RETURN (0, tp == start_of_digits ? (base == 16 ? cp - 1 : nptr) : tp); - } - - /* Remember first significant digit and read following characters until the - decimal point, exponent character or any non-FP number character. */ - startp = cp; - dig_no = 0; - while (1) - { - if ((c >= '0' && c <= '9') - || (base == 16 && tolower (c) >= 'a' && tolower (c) <= 'f')) - ++dig_no; - else - break; - c = *++cp; - } - - /* The whole string is parsed. Store the address of the next character. */ - if (endptr) - *endptr = (char *) cp; - - if (dig_no == 0) - return 0; - - for (p=start_of_digits; p!=cp; p++) { - n = n * (Bit64s)base; - c = tolower (*p); - c = (c >= 'a') ? (10+c-'a') : c-'0'; - n = n + (Bit64s)c; - //printf ("after shifting in digit %c, n is %lld\n", *p, n); - } - return negative? -n : n; -} -#endif /* !BX_HAVE_STRTOULL */ - -#if BX_TEST_STRTOULL_MAIN -/* test driver for strtoull. Do not compile by default. */ -int main (int argc, char **argv) -{ - char buf[256], *endbuf; - long l; - Bit64s ll; - while (1) { - printf ("Enter a long int: "); - gets (buf); - l = strtoul (buf, &endbuf, 10); - printf ("As a long, %ld\n", l); - printf ("Endbuf is at buf[%d]\n", endbuf-buf); - ll = bx_strtoull (buf, &endbuf, 10); - printf ("As a long long, %lld\n", ll); - printf ("Endbuf is at buf[%d]\n", endbuf-buf); - } - return 0; -} -#endif /* BX_TEST_STRTOULL_MAIN */ - -#if !BX_HAVE_STRDUP -/* XXX use real strdup */ -char *bx_strdup(const char *str) -{ - char *temp; - - temp = (char*)malloc(strlen(str)+1); - sprintf(temp, "%s", str); - return temp; - - // Well, I'm sure this isn't how strdup is REALLY implemented, - // but it works... -} -#endif /* !BX_HAVE_STRDUP */ - -#if !BX_HAVE_STRREV -char *bx_strrev(char *str) -{ - char *p1, *p2; - - if (! str || ! *str) - return str; - - for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2) { - *p1 ^= *p2; - *p2 ^= *p1; - *p1 ^= *p2; - } - return str; -} -#endif /* !BX_HAVE_STRREV */ - -#if BX_WITH_MACOS -namespace std{extern "C" {char *mktemp(char *tpl);}} -#endif -#if !BX_HAVE_MKSTEMP -int bx_mkstemp(char *tpl) -{ - mktemp(tpl); - return ::open(tpl, O_RDWR | O_CREAT | O_TRUNC -# ifdef O_BINARY - | O_BINARY -# endif - , S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP); -} -#endif // !BX_HAVE_MKSTEMP - -////////////////////////////////////////////////////////////////////// -// Missing library functions, implemented for MacOS only -////////////////////////////////////////////////////////////////////// - -#if BX_WITH_MACOS -// these functions are part of MacBochs. They are not intended to be -// portable! -#include -#include -#include - -int fd_read(char *buffer, Bit32u offset, Bit32u bytes) -{ - OSErr err; - IOParam param; - - param.ioRefNum=-5; // Refnum of the floppy disk driver - param.ioVRefNum=1; - param.ioPosMode=fsFromStart; - param.ioPosOffset=offset; - param.ioBuffer=buffer; - param.ioReqCount=bytes; - err = PBReadSync((union ParamBlockRec *)(¶m)); - return param.ioActCount; -} - -int fd_write(char *buffer, Bit32u offset, Bit32u bytes) -{ - OSErr err; - IOParam param; - - param.ioRefNum=-5; // Refnum of the floppy disk driver - param.ioVRefNum=1; - param.ioPosMode=fsFromStart; - param.ioPosOffset=offset; - param.ioBuffer=buffer; - param.ioReqCount=bytes; - err = PBWriteSync((union ParamBlockRec *)(¶m)); - return param.ioActCount; -} - -int fd_stat(struct stat *buf) -{ - OSErr err; - DrvSts status; - int result; - - result = 0; - err = DriveStatus(1, &status); - if (status.diskInPlace <1 || status.diskInPlace > 2) - result = -1; - buf->st_mode = S_IFCHR; - return result; -} -#endif /* BX_WITH_MACOS */ - - - -////////////////////////////////////////////////////////////////////// -// New functions to replace library functions -// with OS-independent versions -////////////////////////////////////////////////////////////////////// - -#if BX_HAVE_REALTIME_USEC -# if BX_HAVE_GETTIMEOFDAY -Bit64u bx_get_realtime64_usec (void) { - timeval thetime; - gettimeofday(&thetime,0); - Bit64u mytime; - mytime=(Bit64u)thetime.tv_sec*(Bit64u)1000000+(Bit64u)thetime.tv_usec; - return mytime; -} -# elif defined(WIN32) -Bit64u last_realtime64_top = 0; -Bit64u last_realtime64_bottom = 0; -Bit64u bx_get_realtime64_usec (void) { - Bit64u new_bottom = ((Bit64u) GetTickCount()) & BX_CONST64(0x0FFFFFFFF); - if(new_bottom < last_realtime64_bottom) { - last_realtime64_top += BX_CONST64(0x0000000100000000); - } - last_realtime64_bottom = new_bottom; - Bit64u interim_realtime64 = - (last_realtime64_top & BX_CONST64(0xFFFFFFFF00000000)) | - (new_bottom & BX_CONST64(0x00000000FFFFFFFF)); - return interim_realtime64*(BX_CONST64(1000)); -} -# endif -#endif diff --git a/tools/ioemu/iodev/parallel.cc b/tools/ioemu/iodev/parallel.cc deleted file mode 100644 index 8b0d4b3245..0000000000 --- a/tools/ioemu/iodev/parallel.cc +++ /dev/null @@ -1,300 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: parallel.cc,v 1.24 2003/10/29 17:29:26 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// -//////////////////////////////////////////////////////// -// This code was just a few stubs until Volker.Ruppert@t-online.de -// fixed it up in November 2001. - - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#define LOG_THIS theParallelDevice-> - -bx_parallel_c *theParallelDevice = NULL; - - int -libparallel_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - theParallelDevice = new bx_parallel_c (); - bx_devices.pluginParallelDevice = theParallelDevice; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theParallelDevice, BX_PLUGIN_PARALLEL); - return(0); // Success -} - - void -libparallel_LTX_plugin_fini(void) -{ -} - -bx_parallel_c::bx_parallel_c(void) -{ - put("PAR"); - settype(PARLOG); - s.output = NULL; -} - -bx_parallel_c::~bx_parallel_c(void) -{ - if (s.output != NULL) - fclose(s.output); -} - - void -bx_parallel_c::init(void) -{ - BX_DEBUG(("Init $Id: parallel.cc,v 1.24 2003/10/29 17:29:26 vruppert Exp $")); - - if (bx_options.par[0].Oenabled->get ()) { - - /* PARALLEL PORT 1 */ - - DEV_register_irq(7, "Parallel Port 1"); - BX_INFO (("parallel port 1 at 0x378 irq 7")); - for (unsigned addr=0x0378; addr<=0x037A; addr++) { - DEV_register_ioread_handler(this, read_handler, addr, "Parallel Port 1", 1); - } - DEV_register_iowrite_handler(this, write_handler, 0x0378, "Parallel Port 1", 1); - DEV_register_iowrite_handler(this, write_handler, 0x037A, "Parallel Port 1", 1); - - BX_PAR_THIS s.STATUS.error = 1; - BX_PAR_THIS s.STATUS.slct = 1; - BX_PAR_THIS s.STATUS.pe = 0; - BX_PAR_THIS s.STATUS.ack = 1; - BX_PAR_THIS s.STATUS.busy = 1; - - BX_PAR_THIS s.CONTROL.strobe = 0; - BX_PAR_THIS s.CONTROL.autofeed = 0; - BX_PAR_THIS s.CONTROL.init = 1; - BX_PAR_THIS s.CONTROL.slct_in = 1; - BX_PAR_THIS s.CONTROL.irq = 0; - BX_PAR_THIS s.CONTROL.input = 0; - - BX_PAR_THIS s.initmode = 0; - - if (strlen(bx_options.par[0].Ooutfile->getptr ()) > 0) { - s.output = fopen(bx_options.par[0].Ooutfile->getptr (), "wb"); - if (!s.output) - BX_PANIC (("Could not open '%s' to write parport1 output", - bx_options.par[0].Ooutfile->getptr ())); - } - } -} - - void -bx_parallel_c::reset(unsigned type) -{ -} - - void -bx_parallel_c::virtual_printer(void) -{ - if (BX_PAR_THIS s.STATUS.slct) { - if (BX_PAR_THIS s.output != NULL) { - fputc(BX_PAR_THIS s.data, BX_PAR_THIS s.output); - fflush (BX_PAR_THIS s.output); - } - if (BX_PAR_THIS s.CONTROL.irq == 1) { - DEV_pic_raise_irq(7); - } - BX_PAR_THIS s.STATUS.ack = 0; - BX_PAR_THIS s.STATUS.busy = 1; - } - else { - BX_ERROR(("data is valid, but printer is offline")); - } -} - - // static IO port read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_parallel_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_PAR_SMF - bx_parallel_c *class_ptr = (bx_parallel_c *) this_ptr; - - return( class_ptr->read(address, io_len) ); -} - - - Bit32u -bx_parallel_c::read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PAR_SMF - - Bit32u retval; - - switch (address) { - /* PARALLEL PORT 1 */ - case 0x0378: - if (!BX_PAR_THIS s.CONTROL.input) { - return (Bit32u)BX_PAR_THIS s.data; - } else { - BX_ERROR(("read: input mode not supported")); - return (0xFF); - } - break; - case 0x0379: - { - retval = ((BX_PAR_THIS s.STATUS.busy << 7) | - (BX_PAR_THIS s.STATUS.ack << 6) | - (BX_PAR_THIS s.STATUS.pe << 5) | - (BX_PAR_THIS s.STATUS.slct << 4) | - (BX_PAR_THIS s.STATUS.error << 3)); - if (BX_PAR_THIS s.STATUS.ack == 0) { - BX_PAR_THIS s.STATUS.ack = 1; - if (BX_PAR_THIS s.CONTROL.irq == 1) { - DEV_pic_lower_irq(7); - } - } - if (BX_PAR_THIS s.initmode == 1) { - BX_PAR_THIS s.STATUS.busy = 1; - BX_PAR_THIS s.STATUS.slct = 1; - BX_PAR_THIS s.STATUS.ack = 0; - if (BX_PAR_THIS s.CONTROL.irq == 1) { - DEV_pic_raise_irq(7); - } - BX_PAR_THIS s.initmode = 0; - } - BX_DEBUG(("read: status register returns 0x%02x", retval)); - return retval; - } - break; - case 0x037A: - { - retval = ((BX_PAR_THIS s.CONTROL.input << 5) | - (BX_PAR_THIS s.CONTROL.irq << 4) | - (BX_PAR_THIS s.CONTROL.slct_in << 3) | - (BX_PAR_THIS s.CONTROL.init << 2) | - (BX_PAR_THIS s.CONTROL.autofeed << 1) | - (BX_PAR_THIS s.CONTROL.strobe)); - BX_DEBUG(("read: control register returns 0x%02x", retval)); - return retval; - } - break; - } - return(0); -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_parallel_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_PAR_SMF - bx_parallel_c *class_ptr = (bx_parallel_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - - void -bx_parallel_c::write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PAR_SMF - - switch (address) { - /* PARALLEL PORT 1 */ - case 0x0378: - BX_PAR_THIS s.data = (Bit8u)value; - BX_DEBUG(("write: data output register = 0x%02x", (Bit8u)value)); - break; - case 0x037A: - { - if ((value & 0x01) == 0x01) { - if (BX_PAR_THIS s.CONTROL.strobe == 0) { - BX_PAR_THIS s.CONTROL.strobe = 1; - virtual_printer(); // data is valid now - } - } else { - if (BX_PAR_THIS s.CONTROL.strobe == 1) { - BX_PAR_THIS s.CONTROL.strobe = 0; - } - } - BX_PAR_THIS s.CONTROL.autofeed = ((value & 0x02) == 0x02); - if ((value & 0x04) == 0x04) { - if (BX_PAR_THIS s.CONTROL.init == 0) { - BX_PAR_THIS s.CONTROL.init = 1; - BX_PAR_THIS s.STATUS.busy = 0; - BX_PAR_THIS s.STATUS.slct = 0; - BX_PAR_THIS s.initmode = 1; - BX_DEBUG(("printer init requested")); - } - } else { - if (BX_PAR_THIS s.CONTROL.init == 1) { - BX_PAR_THIS s.CONTROL.init = 0; - } - } - if ((value & 0x08) == 0x08) { - if (BX_PAR_THIS s.CONTROL.slct_in == 0) { - BX_PAR_THIS s.CONTROL.slct_in = 1; - BX_DEBUG(("printer now online")); - } - } else { - if (BX_PAR_THIS s.CONTROL.slct_in == 1) { - BX_PAR_THIS s.CONTROL.slct_in = 0; - BX_DEBUG(("printer now offline")); - } - } - BX_PAR_THIS s.STATUS.slct = BX_PAR_THIS s.CONTROL.slct_in; - if ((value & 0x10) == 0x10) { - if (BX_PAR_THIS s.CONTROL.irq == 0) { - BX_PAR_THIS s.CONTROL.irq = 1; - BX_DEBUG(("irq mode selected")); - } - } else { - if (BX_PAR_THIS s.CONTROL.irq == 1) { - BX_PAR_THIS s.CONTROL.irq = 0; - BX_DEBUG(("polling mode selected")); - } - } - if ((value & 0x20) == 0x20) { - if (BX_PAR_THIS s.CONTROL.input == 0) { - BX_PAR_THIS s.CONTROL.input = 1; - BX_DEBUG(("data input mode selected")); - } - } else { - if (BX_PAR_THIS s.CONTROL.input == 1) { - BX_PAR_THIS s.CONTROL.input = 0; - BX_DEBUG(("data output mode selected")); - } - } - if ((value & 0xC0) > 0) { - BX_ERROR(("write: unsupported control bit ignored")); - } - } - break; - } -} diff --git a/tools/ioemu/iodev/parallel.h b/tools/ioemu/iodev/parallel.h deleted file mode 100644 index b4a256a616..0000000000 --- a/tools/ioemu/iodev/parallel.h +++ /dev/null @@ -1,78 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: parallel.h,v 1.11 2002/10/25 11:44:40 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -#if BX_USE_PAR_SMF -# define BX_PAR_SMF static -# define BX_PAR_THIS theParallelDevice-> -#else -# define BX_PAR_SMF -# define BX_PAR_THIS this-> -#endif - -typedef struct { - Bit8u data; - struct { - bx_bool error; - bx_bool slct; - bx_bool pe; - bx_bool ack; - bx_bool busy; - } STATUS; - struct { - bx_bool strobe; - bx_bool autofeed; - bx_bool init; - bx_bool slct_in; - bx_bool irq; - bx_bool input; - } CONTROL; - FILE *output; - bx_bool initmode; -} bx_par_t; - - - -class bx_parallel_c : public bx_devmodel_c { -public: - - bx_parallel_c(void); - ~bx_parallel_c(void); - virtual void init(void); - virtual void reset(unsigned type); - -private: - bx_par_t s; - - static void virtual_printer(); - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); -#if !BX_USE_PAR_SMF - Bit32u read(Bit32u address, unsigned io_len); - void write(Bit32u address, Bit32u value, unsigned io_len); -#endif - }; diff --git a/tools/ioemu/iodev/pc_system.cc b/tools/ioemu/iodev/pc_system.cc deleted file mode 100644 index de34d9914b..0000000000 --- a/tools/ioemu/iodev/pc_system.cc +++ /dev/null @@ -1,570 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pc_system.cc,v 1.34 2003/06/07 19:16:51 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - -#include "bochs.h" -#define LOG_THIS bx_pc_system. - -#ifdef WIN32 -#ifndef __MINGW32__ -// #include // +++ -#include -#endif -#endif - -#if BX_SHOW_IPS -unsigned long ips_count=0; -#endif - -#if defined(PROVIDE_M_IPS) -double m_ips; // Millions of Instructions Per Second -#endif - -#ifdef BX_USE_VMX -unsigned int tsc_per_bx_tick; -#endif - -// Option for turning off BX_TIMER_DEBUG? -// Check out m_ips and ips - -#define SpewPeriodicTimerInfo 0 -#define MinAllowableTimerPeriod 1 - - -#if SpewPeriodicTimerInfo -// If debugging, set the heartbeat to 5M cycles. Each heartbeat -// spews the active timer info. -const Bit64u bx_pc_system_c::NullTimerInterval = 5000000; -#else -// This must be the maximum 32-bit unsigned int value, NOT (Bit64u) -1. -const Bit64u bx_pc_system_c::NullTimerInterval = 0xffffffff; -#endif - - // constructor -bx_pc_system_c::bx_pc_system_c(void) -{ - this->put("SYS"); - - // Timer[0] is the null timer. It is initialized as a special - // case here. It should never be turned off or modified, and its - // duration should always remain the same. - ticksTotal = 0; // Reset ticks since emulator started. - timer[0].period = NullTimerInterval; - timer[0].timeToFire = ticksTotal + NullTimerInterval; - timer[0].active = 1; - timer[0].continuous = 1; - timer[0].funct = nullTimer; - timer[0].this_ptr = this; - currCountdown = NullTimerInterval; - currCountdownPeriod = NullTimerInterval; - numTimers = 1; // So far, only the nullTimer. - lastTimeUsec = 0; - usecSinceLast = 0; -} - - void -bx_pc_system_c::init_ips(Bit32u ips) -{ - HRQ = 0; - - enable_a20 = 1; - //set_INTR (0); - -#if BX_CPU_LEVEL < 2 - a20_mask = 0xfffff; -#elif BX_CPU_LEVEL == 2 - a20_mask = 0xffffff; -#else /* 386+ */ - a20_mask = 0xffffffff; -#endif - -#ifdef BX_USE_VMX - Bit64u phy_cpu_freq = cpu_calibrate_ticks(); - - if (ips == 500000) { //default ips: we use fixed scaling factor to calulate ips - tsc_per_bx_tick = 2000; - ips = phy_cpu_freq / tsc_per_bx_tick; - } else //use uesr defined ips to calulate factor - tsc_per_bx_tick = ((phy_cpu_freq + (ips>>1)) / ips); -#endif - - // parameter 'ips' is the processor speed in Instructions-Per-Second - m_ips = double(ips) / 1000000.0L; - - BX_DEBUG(("ips = %u", (unsigned) ips)); -} - - void -bx_pc_system_c::set_HRQ(bx_bool val) -{ - HRQ = val; - if (val) - BX_CPU(0)->async_event = 1; -} - - -#if (BX_NUM_SIMULATORS < 2) - void -bx_pc_system_c::set_INTR(bx_bool value) -{ - if (bx_dbg.interrupts) - BX_INFO(("pc_system: Setting INTR=%d on bootstrap processor %d", (int)value, BX_BOOTSTRAP_PROCESSOR)); - //INTR = value; - BX_CPU(BX_BOOTSTRAP_PROCESSOR)->set_INTR(value); -} -#endif - -// -// Read from the IO memory address space -// - - Bit32u BX_CPP_AttrRegparmN(2) -bx_pc_system_c::inp(Bit16u addr, unsigned io_len) -{ - Bit32u ret; - - ret = bx_devices.inp(addr, io_len); - - return( ret ); -} - - -// -// Write to the IO memory address space. -// - - void BX_CPP_AttrRegparmN(3) -bx_pc_system_c::outp(Bit16u addr, Bit32u value, unsigned io_len) -{ - bx_devices.outp(addr, value, io_len); -} - - void BX_CPP_AttrRegparmN(1) -bx_pc_system_c::set_enable_a20(Bit8u value) -{ -#if BX_CPU_LEVEL < 2 - BX_PANIC(("set_enable_a20() called: 8086 emulation")); -#else - -#if BX_SUPPORT_A20 - unsigned old_enable_a20 = enable_a20; - - if (value) { - enable_a20 = 1; -#if BX_CPU_LEVEL == 2 - a20_mask = 0xffffff; /* 286: enable all 24 address lines */ -#else /* 386+ */ - a20_mask = 0xffffffff; /* 386: enable all 32 address lines */ -#endif - } - else { - enable_a20 = 0; - a20_mask = 0xffefffff; /* mask off A20 address line */ - } - - BX_DBG_A20_REPORT(value); - - BX_DEBUG(("A20: set() = %u", (unsigned) enable_a20)); - - // If there has been a transition, we need to notify the CPUs so - // they can potentially invalidate certain cache info based on - // A20-line-applied physical addresses. - if (old_enable_a20 != enable_a20) { - for (unsigned i=0; ipagingA20Changed(); - } -#else - BX_DEBUG(("set_enable_a20: ignoring: SUPPORT_A20 = 0")); -#endif // #if BX_SUPPORT_A20 - -#endif -} - - bx_bool -bx_pc_system_c::get_enable_a20(void) -{ -#if BX_SUPPORT_A20 - if (bx_dbg.a20) - BX_INFO(("A20: get() = %u", (unsigned) enable_a20)); - - if (enable_a20) return(1); - else return(0); -#else - BX_INFO(("get_enable_a20: ignoring: SUPPORT_A20 = 0")); - return(1); -#endif // #if BX_SUPPORT_A20 -} - - int -bx_pc_system_c::ResetSignal( PCS_OP operation ) -{ - UNUSED( operation ); - // Reset the processor. - - BX_ERROR(( "# bx_pc_system_c::ResetSignal() called" )); - for (int i=0; ireset(BX_RESET_SOFTWARE); - DEV_reset_devices(BX_RESET_SOFTWARE); - return(0); -} - - - Bit8u -bx_pc_system_c::IAC(void) -{ - return( DEV_pic_iac() ); -} - - void -bx_pc_system_c::exit(void) -{ - if (DEV_hd_present()) - DEV_hd_close_harddrive(); - - BX_INFO(("Last time is %u", (unsigned) DEV_cmos_get_timeval())); - - if (bx_gui) bx_gui->exit(); -} - - -// ================================================ -// Bochs internal timer delivery framework features -// ================================================ - - int -bx_pc_system_c::register_timer( void *this_ptr, void (*funct)(void *), - Bit32u useconds, bx_bool continuous, bx_bool active, const char *id) -{ - Bit64u ticks; - - // Convert useconds to number of ticks. - ticks = (Bit64u) (double(useconds) * m_ips); - - return register_timer_ticks(this_ptr, funct, ticks, continuous, active, id); -} - - int -bx_pc_system_c::register_timer_ticks(void* this_ptr, bx_timer_handler_t funct, - Bit64u ticks, bx_bool continuous, bx_bool active, const char *id) -{ - unsigned i; - -#if BX_TIMER_DEBUG - if (numTimers >= BX_MAX_TIMERS) { - BX_PANIC(("register_timer: too many registered timers.")); - } - if (this_ptr == NULL) - BX_PANIC(("register_timer_ticks: this_ptr is NULL")); - if (funct == NULL) - BX_PANIC(("register_timer_ticks: funct is NULL")); -#endif - - // If the timer frequency is rediculously low, make it more sane. - // This happens when 'ips' is too low. - if (ticks < MinAllowableTimerPeriod) { - //BX_INFO(("register_timer_ticks: adjusting ticks of %llu to min of %u", - // ticks, MinAllowableTimerPeriod)); - ticks = MinAllowableTimerPeriod; - } - - for (i=0; i < numTimers; i++) { - if (timer[i].inUse == 0) - break; - } - - timer[i].inUse = 1; - timer[i].period = ticks; - timer[i].timeToFire = (ticksTotal + Bit64u(currCountdownPeriod-currCountdown)) + - ticks; - timer[i].active = active; - timer[i].continuous = continuous; - timer[i].funct = funct; - timer[i].this_ptr = this_ptr; - strncpy(timer[i].id, id, BxMaxTimerIDLen); - timer[i].id[BxMaxTimerIDLen-1] = 0; // Null terminate if not already. - - if (active) { - if (ticks < Bit64u(currCountdown)) { - // This new timer needs to fire before the current countdown. - // Skew the current countdown and countdown period to be smaller - // by the delta. - currCountdownPeriod -= (currCountdown - Bit32u(ticks)); - currCountdown = Bit32u(ticks); - } - } - - // If we didn't find a free slot, increment the bound, numTimers. - if (i==numTimers) - numTimers++; // One new timer installed. - - // Return timer id. - return(i); -} - - - void -bx_pc_system_c::countdownEvent(void) -{ - unsigned i; - Bit64u minTimeToFire; - bx_bool triggered[BX_MAX_TIMERS]; - - // The countdown decremented to 0. We need to service all the active - // timers, and invoke callbacks from those timers which have fired. -#if BX_TIMER_DEBUG - if (currCountdown != 0) - BX_PANIC(("countdownEvent: ticks!=0")); -#endif - - // Increment global ticks counter by number of ticks which have - // elapsed since the last update. - ticksTotal += Bit64u(currCountdownPeriod); - minTimeToFire = (Bit64u) -1; - - for (i=0; i < numTimers; i++) { - triggered[i] = 0; // Reset triggered flag. - if (timer[i].active) { -#if BX_TIMER_DEBUG - if (ticksTotal > timer[i].timeToFire) - BX_PANIC(("countdownEvent: ticksTotal > timeToFire[%u], D " FMT_LL "u", i, - timer[i].timeToFire-ticksTotal)); -#endif - if (ticksTotal == timer[i].timeToFire) { - // This timer is ready to fire. - triggered[i] = 1; - - if (timer[i].continuous==0) { - // If triggered timer is one-shot, deactive. - timer[i].active = 0; - } - else { - // Continuous timer, increment time-to-fire by period. - timer[i].timeToFire += timer[i].period; - if (timer[i].timeToFire < minTimeToFire) - minTimeToFire = timer[i].timeToFire; - } - } - else { - // This timer is not ready to fire yet. - if (timer[i].timeToFire < minTimeToFire) - minTimeToFire = timer[i].timeToFire; - } - } - } - - // Calculate next countdown period. We need to do this before calling - // any of the callbacks, as they may call timer features, which need - // to be advanced to the next countdown cycle. - currCountdown = currCountdownPeriod = - Bit32u(minTimeToFire - ticksTotal); - - for (i=0; i < numTimers; i++) { - // Call requested timer function. It may request a different - // timer period or deactivate etc. - if (triggered[i]) { - timer[i].funct(timer[i].this_ptr); - } - } -} - - void -bx_pc_system_c::nullTimer(void* this_ptr) -{ - // This function is always inserted in timer[0]. It is sort of - // a heartbeat timer. It ensures that at least one timer is - // always active to make the timer logic more simple, and has - // a duration of less than the maximum 32-bit integer, so that - // a 32-bit size can be used for the hot countdown timer. The - // rest of the timer info can be 64-bits. This is also a good - // place for some logic to report actual emulated - // instructions-per-second (IPS) data when measured relative to - // the host computer's wall clock. - - UNUSED(this_ptr); - -#if SpewPeriodicTimerInfo - BX_INFO(("===================================")); - for (unsigned i=0; i < bx_pc_system.numTimers; i++) { - if (bx_pc_system.timer[i].active) { - BX_INFO(("BxTimer(%s): period=" FMT_LL "u, continuous=%u", - bx_pc_system.timer[i].id, bx_pc_system.timer[i].period, - bx_pc_system.timer[i].continuous)); - } - } -#endif -} - -#if BX_DEBUGGER - void -bx_pc_system_c::timebp_handler(void* this_ptr) -{ - BX_CPU(0)->break_point = BREAK_POINT_TIME; - BX_DEBUG(( "Time breakpoint triggered" )); - - if (timebp_queue_size > 1) { - Bit64s new_diff = timebp_queue[1] - bx_pc_system.time_ticks(); - bx_pc_system.activate_timer_ticks(timebp_timer, new_diff, 1); - } - timebp_queue_size--; - for (int i = 0; i < timebp_queue_size; i++) - timebp_queue[i] = timebp_queue[i+1]; -} -#endif // BX_DEBUGGER - - Bit64u -bx_pc_system_c::time_usec_sequential() { - Bit64u this_time_usec = time_usec(); - if(this_time_usec != lastTimeUsec) { - Bit64u diff_usec = this_time_usec-lastTimeUsec; - lastTimeUsec = this_time_usec; - if(diff_usec >= usecSinceLast) { - usecSinceLast = 0; - } else { - usecSinceLast -= diff_usec; - } - } - usecSinceLast++; - return (this_time_usec+usecSinceLast); -} - Bit64u -bx_pc_system_c::time_usec() { - return (Bit64u) (((double)(Bit64s)time_ticks()) / m_ips ); -} - - void -bx_pc_system_c::start_timers(void) -{ -} - - void -bx_pc_system_c::activate_timer_ticks(unsigned i, Bit64u ticks, bx_bool continuous) -{ -#if BX_TIMER_DEBUG - if (i >= numTimers) - BX_PANIC(("activate_timer_ticks: timer %u OOB", i)); - if (timer[i].period < MinAllowableTimerPeriod) - BX_PANIC(("activate_timer_ticks: timer[%u].period of " FMT_LL "u < min of %u", - i, timer[i].period, MinAllowableTimerPeriod)); -#endif - - // If the timer frequency is rediculously low, make it more sane. - // This happens when 'ips' is too low. - if (ticks < MinAllowableTimerPeriod) { - //BX_INFO(("activate_timer_ticks: adjusting ticks of %llu to min of %u", - // ticks, MinAllowableTimerPeriod)); - ticks = MinAllowableTimerPeriod; - } - - timer[i].period = ticks; - timer[i].timeToFire = (ticksTotal + Bit64u(currCountdownPeriod-currCountdown)) + - ticks; - timer[i].active = 1; - timer[i].continuous = continuous; - - if (ticks < Bit64u(currCountdown)) { - // This new timer needs to fire before the current countdown. - // Skew the current countdown and countdown period to be smaller - // by the delta. - currCountdownPeriod -= (currCountdown - Bit32u(ticks)); - currCountdown = Bit32u(ticks); - } -} - - void -bx_pc_system_c::activate_timer(unsigned i, Bit32u useconds, bx_bool continuous) -{ - Bit64u ticks; - -#if BX_TIMER_DEBUG - if (i >= numTimers) - BX_PANIC(("activate_timer: timer %u OOB", i)); -#endif - - // if useconds = 0, use default stored in period field - // else set new period from useconds - if (useconds==0) { - ticks = timer[i].period; - } - else { - // convert useconds to number of ticks - ticks = (Bit64u) (double(useconds) * m_ips); - - // If the timer frequency is rediculously low, make it more sane. - // This happens when 'ips' is too low. - if (ticks < MinAllowableTimerPeriod) { - //BX_INFO(("activate_timer: adjusting ticks of %llu to min of %u", - // ticks, MinAllowableTimerPeriod)); - ticks = MinAllowableTimerPeriod; - } - - timer[i].period = ticks; - } - - activate_timer_ticks(i, ticks, continuous); -} - - void -bx_pc_system_c::deactivate_timer( unsigned i ) -{ -#if BX_TIMER_DEBUG - if (i >= numTimers) - BX_PANIC(("deactivate_timer: timer %u OOB", i)); -#endif - - timer[i].active = 0; -} - - unsigned -bx_pc_system_c::unregisterTimer(int timerIndex) -{ - unsigned i = (unsigned) timerIndex; - -#if BX_TIMER_DEBUG - if (i >= numTimers) - BX_PANIC(("unregisterTimer: timer %u OOB", i)); - if (i == 0) - BX_PANIC(("unregisterTimer: timer 0 is the nullTimer!")); - if (timer[i].inUse == 0) - BX_PANIC(("unregisterTimer: timer %u is not in-use!", i)); -#endif - - if (timer[i].active) { - BX_PANIC(("unregisterTimer: timer '%s' is still active!", timer[i].id)); - return(0); // Fail. - } - - // Reset timer fields for good measure. - timer[i].inUse = 0; // No longer registered. - timer[i].period = BX_MAX_BIT64S; // Max value (invalid) - timer[i].timeToFire = BX_MAX_BIT64S; // Max value (invalid) - timer[i].continuous = 0; - timer[i].funct = NULL; - timer[i].this_ptr = NULL; - memset(timer[i].id, 0, BxMaxTimerIDLen); - - return(1); // OK -} diff --git a/tools/ioemu/iodev/pci.cc b/tools/ioemu/iodev/pci.cc deleted file mode 100644 index 6dfe5dbbad..0000000000 --- a/tools/ioemu/iodev/pci.cc +++ /dev/null @@ -1,467 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pci.cc,v 1.29 2003/07/31 19:51:42 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// -// i440FX Support - PMC/DBX -// - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_PCI_SUPPORT - -#define LOG_THIS thePciBridge-> - -bx_pci_c *thePciBridge = NULL; - - int -libpci_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - thePciBridge = new bx_pci_c (); - bx_devices.pluginPciBridge = thePciBridge; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePciBridge, BX_PLUGIN_PCI); - return(0); // Success -} - - void -libpci_LTX_plugin_fini(void) -{ -} - -bx_pci_c::bx_pci_c(void) -{ - put("PCI"); - settype(PCILOG); -} - -bx_pci_c::~bx_pci_c(void) -{ - // nothing for now - BX_DEBUG(("Exit.")); -} - - - void -bx_pci_c::init(void) -{ - // called once when bochs initializes - unsigned i; - BX_PCI_THIS num_pci_handles = 0; - - /* set unused elements to appropriate values */ - for (i=0; i < BX_MAX_PCI_DEVICES; i++) { - BX_PCI_THIS pci_handler[i].read = NULL; - BX_PCI_THIS pci_handler[i].write = NULL; - } - - for (i=0; i < 0x100; i++) { - BX_PCI_THIS pci_handler_id[i] = BX_MAX_PCI_DEVICES; // not assigned - } - - // confAddr accepts dword i/o only - DEV_register_ioread_handler(this, read_handler, 0x0CF8, "i440FX", 4); - DEV_register_iowrite_handler(this, write_handler, 0x0CF8, "i440FX", 4); - - for (i=0x0CFC; i<=0x0CFF; i++) { - DEV_register_ioread_handler(this, read_handler, i, "i440FX", 7); - } - for (i=0x0CFC; i<=0x0CFF; i++) { - DEV_register_iowrite_handler(this, write_handler, i, "i440FX", 7); - } - - DEV_register_pci_handlers(this, pci_read_handler, pci_write_handler, - BX_PCI_DEVICE(0,0), "440FX Host bridge"); - - for (i=0; i<256; i++) - BX_PCI_THIS s.i440fx.pci_conf[i] = 0x0; - // readonly registers - BX_PCI_THIS s.i440fx.pci_conf[0x00] = 0x86; - BX_PCI_THIS s.i440fx.pci_conf[0x01] = 0x80; - BX_PCI_THIS s.i440fx.pci_conf[0x02] = 0x37; - BX_PCI_THIS s.i440fx.pci_conf[0x03] = 0x12; - BX_PCI_THIS s.i440fx.pci_conf[0x0b] = 0x06; -} - - void -bx_pci_c::reset(unsigned type) -{ - BX_PCI_THIS s.i440fx.confAddr = 0; - BX_PCI_THIS s.i440fx.confData = 0; - - BX_PCI_THIS s.i440fx.pci_conf[0x04] = 0x06; - BX_PCI_THIS s.i440fx.pci_conf[0x05] = 0x00; - BX_PCI_THIS s.i440fx.pci_conf[0x06] = 0x80; - BX_PCI_THIS s.i440fx.pci_conf[0x07] = 0x02; - BX_PCI_THIS s.i440fx.pci_conf[0x0d] = 0x00; - BX_PCI_THIS s.i440fx.pci_conf[0x0f] = 0x00; - BX_PCI_THIS s.i440fx.pci_conf[0x50] = 0x00; - BX_PCI_THIS s.i440fx.pci_conf[0x51] = 0x01; - BX_PCI_THIS s.i440fx.pci_conf[0x52] = 0x00; - BX_PCI_THIS s.i440fx.pci_conf[0x53] = 0x80; - BX_PCI_THIS s.i440fx.pci_conf[0x54] = 0x00; - BX_PCI_THIS s.i440fx.pci_conf[0x55] = 0x00; - BX_PCI_THIS s.i440fx.pci_conf[0x56] = 0x00; - BX_PCI_THIS s.i440fx.pci_conf[0x57] = 0x01; - BX_PCI_THIS s.i440fx.pci_conf[0x58] = 0x10; - for (unsigned i=0x59; i<0x60; i++) - BX_PCI_THIS s.i440fx.pci_conf[i] = 0x00; -} - - - - // static IO port read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_pci_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_PCI_SMF - bx_pci_c *class_ptr = (bx_pci_c *) this_ptr; - - return( class_ptr->read(address, io_len) ); -} - - - Bit32u -bx_pci_c::read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PCI_SMF - - switch (address) { - case 0x0CF8: - { - return BX_PCI_THIS s.i440fx.confAddr; - } - break; - case 0x0CFC: - case 0x0CFD: - case 0x0CFE: - case 0x0CFF: - { - Bit32u handle, retval; - Bit8u devfunc, regnum; - - if ((BX_PCI_THIS s.i440fx.confAddr & 0x80FF0000) == 0x80000000) { - devfunc = (BX_PCI_THIS s.i440fx.confAddr >> 8) & 0xff; - regnum = (BX_PCI_THIS s.i440fx.confAddr & 0xfc) + (address & 0x03); - handle = BX_PCI_THIS pci_handler_id[devfunc]; - if ((io_len <= 4) && (handle < BX_MAX_PCI_DEVICES)) - retval = (* BX_PCI_THIS pci_handler[handle].read) - (BX_PCI_THIS pci_handler[handle].this_ptr, regnum, io_len); - else - retval = 0xFFFFFFFF; - } - else - retval = 0xFFFFFFFF; - BX_PCI_THIS s.i440fx.confData = retval; - return retval; - } - } - - BX_PANIC(("unsupported IO read to port 0x%x", - (unsigned) address)); - return(0xffffffff); -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_pci_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_PCI_SMF - bx_pci_c *class_ptr = (bx_pci_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - - void -bx_pci_c::write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PCI_SMF - - switch (address) { - case 0xCF8: - { - BX_PCI_THIS s.i440fx.confAddr = value; - if ((value & 0x80FFFF00) == 0x80000000) { - BX_DEBUG(("440FX PMC register 0x%02x selected", value & 0xfc)); - } else if ((value & 0x80000000) == 0x80000000) { - BX_DEBUG(("440FX request for bus 0x%02x device 0x%02x function 0x%02x", - (value >> 16) & 0xFF, (value >> 11) & 0x1F, (value >> 8) & 0x07)); - } - } - break; - - case 0xCFC: - case 0xCFD: - case 0xCFE: - case 0xCFF: - { - Bit32u handle; - Bit8u devfunc, regnum; - - if ((BX_PCI_THIS s.i440fx.confAddr & 0x80FF0000) == 0x80000000) { - devfunc = (BX_PCI_THIS s.i440fx.confAddr >> 8) & 0xff; - regnum = (BX_PCI_THIS s.i440fx.confAddr & 0xfc) + (address & 0x03); - handle = BX_PCI_THIS pci_handler_id[devfunc]; - if ((io_len <= 4) && (handle < BX_MAX_PCI_DEVICES)) { - if (((regnum>=4) && (regnum<=7)) || (regnum==12) || (regnum==13) || (regnum>14)) { - (* BX_PCI_THIS pci_handler[handle].write) - (BX_PCI_THIS pci_handler[handle].this_ptr, regnum, value, io_len); - BX_PCI_THIS s.i440fx.confData = value << (8 * (address & 0x03)); - } - else - BX_DEBUG(("read only register, write ignored")); - } - } - } - break; - - default: - BX_PANIC(("IO write to port 0x%x", (unsigned) address)); - } -} - - - // static pci configuration space read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_pci_c::pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len) -{ -#if !BX_USE_PCI_SMF - bx_pci_c *class_ptr = (bx_pci_c *) this_ptr; - - return( class_ptr->pci_read(address, io_len) ); -} - - - Bit32u -bx_pci_c::pci_read(Bit8u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PCI_SMF - - Bit32u val440fx = 0; - - if (io_len <= 4) { - for (unsigned i=0; ipci_write(address, value, io_len); -} - - void -bx_pci_c::pci_write(Bit8u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PCI_SMF - - Bit8u value8; - - if (io_len <= 4) { - for (unsigned i=0; i> (i*8)) & 0xFF; - switch (address+i) { - case 0x06: - case 0x0c: - break; - default: - BX_PCI_THIS s.i440fx.pci_conf[address+i] = value8; - BX_DEBUG(("440FX PMC write register 0x%02x value 0x%02x", address, - value8)); - } - } - } -} - - - Bit8u -bx_pci_c::rd_memType (Bit32u addr) -{ - switch ((addr & 0xFC000) >> 12) { - case 0xC0: - return (BX_PCI_THIS s.i440fx.pci_conf[0x5A] & 0x1); - case 0xC4: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5A] >> 4) & 0x1); - case 0xC8: - return (BX_PCI_THIS s.i440fx.pci_conf[0x5B] & 0x1); - case 0xCC: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5B] >> 4) & 0x1); - - - case 0xD0: - return (BX_PCI_THIS s.i440fx.pci_conf[0x5C] & 0x1); - case 0xD4: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5C] >> 4) & 0x1); - case 0xD8: - return (BX_PCI_THIS s.i440fx.pci_conf[0x5D] & 0x1); - case 0xDC: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5D] >> 4) & 0x1); - - case 0xE0: - return (BX_PCI_THIS s.i440fx.pci_conf[0x5E] & 0x1); - case 0xE4: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5E] >> 4) & 0x1); - case 0xE8: - return (BX_PCI_THIS s.i440fx.pci_conf[0x5F] & 0x1); - case 0xEC: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5F] >> 4) & 0x1); - - case 0xF0: - case 0xF4: - case 0xF8: - case 0xFC: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x59] >> 4) & 0x1); - - default: - BX_PANIC(("rd_memType () Error: Memory Type not known !")); - return(0); // keep compiler happy - break; - } - -} - - Bit8u -bx_pci_c::wr_memType (Bit32u addr) -{ - switch ((addr & 0xFC000) >> 12) { - case 0xC0: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5A] >> 1) & 0x1); - case 0xC4: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5A] >> 5) & 0x1); - case 0xC8: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5B] >> 1) & 0x1); - case 0xCC: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5B] >> 5) & 0x1); - - - case 0xD0: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5C] >> 1) & 0x1); - case 0xD4: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5C] >> 5) & 0x1); - case 0xD8: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5D] >> 1) & 0x1); - case 0xDC: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5D] >> 5) & 0x1); - - case 0xE0: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5E] >> 1) & 0x1); - case 0xE4: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5E] >> 5) & 0x1); - case 0xE8: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5F] >> 1) & 0x1); - case 0xEC: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5F] >> 5) & 0x1); - - case 0xF0: - case 0xF4: - case 0xF8: - case 0xFC: - return ( (BX_PCI_THIS s.i440fx.pci_conf[0x59] >> 5) & 0x1); - - default: - BX_PANIC(("wr_memType () Error: Memory Type not known !")); - return(0); // keep compiler happy - break; - } -} - - void -bx_pci_c::print_i440fx_state() -{ - int i; - - BX_DEBUG(( "i440fxConfAddr:0x%08x", BX_PCI_THIS s.i440fx.confAddr )); - BX_DEBUG(( "i440fxConfData:0x%08x", BX_PCI_THIS s.i440fx.confData )); - -#ifdef DUMP_FULL_I440FX - for (i=0; i<256; i++) { - BX_DEBUG(( "i440fxArray%02x:0x%02x", i, BX_PCI_THIS s.i440fx.pci_conf[i] )); - } -#else /* DUMP_FULL_I440FX */ - for (i=0x59; i<0x60; i++) { - BX_DEBUG(( "i440fxArray%02x:0x%02x", i, BX_PCI_THIS s.i440fx.pci_conf[i] )); - } -#endif /* DUMP_FULL_I440FX */ -} - - bx_bool -bx_pci_c::register_pci_handlers( void *this_ptr, bx_pci_read_handler_t f1, - bx_pci_write_handler_t f2, Bit8u devfunc, - const char *name) -{ - unsigned handle; - - /* first check if device/function is available */ - if (BX_PCI_THIS pci_handler_id[devfunc] == BX_MAX_PCI_DEVICES) { - if (BX_PCI_THIS num_pci_handles >= BX_MAX_PCI_DEVICES) { - BX_INFO(("too many PCI devices installed.")); - BX_PANIC((" try increasing BX_MAX_PCI_DEVICES")); - return false; - } - handle = BX_PCI_THIS num_pci_handles++; - BX_PCI_THIS pci_handler[handle].read = f1; - BX_PCI_THIS pci_handler[handle].write = f2; - BX_PCI_THIS pci_handler[handle].this_ptr = this_ptr; - BX_PCI_THIS pci_handler_id[devfunc] = handle; - BX_INFO(("%s present at device %d, function %d", name, devfunc >> 3, - devfunc & 0x07)); - return true; // device/function mapped successfully - } - else { - return false; // device/function not available, return false. - } -} -#endif /* BX_PCI_SUPPORT */ diff --git a/tools/ioemu/iodev/pci.h b/tools/ioemu/iodev/pci.h deleted file mode 100644 index 92e7beef4f..0000000000 --- a/tools/ioemu/iodev/pci.h +++ /dev/null @@ -1,90 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pci.h,v 1.14 2003/01/23 19:31:27 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -#define BX_MAX_PCI_DEVICES 20 - -#define BX_PCI_DEVICE(device, function) ((device)<<3 | (function)) - -typedef Bit32u (*bx_pci_read_handler_t)(void *, Bit8u, unsigned); -typedef void (*bx_pci_write_handler_t)(void *, Bit8u, Bit32u, unsigned); - -#if BX_USE_PCI_SMF -# define BX_PCI_SMF static -# define BX_PCI_THIS thePciBridge-> -#else -# define BX_PCI_SMF -# define BX_PCI_THIS this-> -#endif - - -typedef struct { - Bit32u confAddr; - Bit32u confData; - Bit8u pci_conf[256]; - } bx_def440fx_t; - - - -class bx_pci_c : public bx_pci_stub_c { - -public: - bx_pci_c(void); - ~bx_pci_c(void); - virtual void init(void); - virtual void reset(unsigned type); - virtual bx_bool register_pci_handlers(void *this_ptr, - bx_pci_read_handler_t f1, - bx_pci_write_handler_t f2, - Bit8u devfunc, const char *name); - virtual void print_i440fx_state(void); - virtual Bit8u rd_memType (Bit32u addr); - virtual Bit8u wr_memType (Bit32u addr); - -private: - Bit8u pci_handler_id[0x100]; // 256 devices/functions - struct { - bx_pci_read_handler_t read; - bx_pci_write_handler_t write; - void *this_ptr; - } pci_handler[BX_MAX_PCI_DEVICES]; - unsigned num_pci_handles; - - struct { - bx_def440fx_t i440fx; - } s; - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); - static Bit32u pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len); - static void pci_write_handler(void *this_ptr, Bit8u address, Bit32u value, unsigned io_len); -#if !BX_USE_PCI_SMF - Bit32u read(Bit32u address, unsigned io_len); - void write(Bit32u address, Bit32u value, unsigned io_len); - Bit32u pci_read(Bit8u address, unsigned io_len); - void pci_write(Bit8u address, Bit32u value, unsigned io_len); -#endif - }; diff --git a/tools/ioemu/iodev/pci2isa.cc b/tools/ioemu/iodev/pci2isa.cc deleted file mode 100644 index 54c3bc441a..0000000000 --- a/tools/ioemu/iodev/pci2isa.cc +++ /dev/null @@ -1,294 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pci2isa.cc,v 1.10 2003/07/31 19:51:42 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// -// i440FX Support - PCI-to-ISA bridge (PIIX3) -// - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_PCI_SUPPORT - -#define LOG_THIS thePci2IsaBridge-> - -bx_pci2isa_c *thePci2IsaBridge = NULL; - - int -libpci2isa_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - thePci2IsaBridge = new bx_pci2isa_c (); - bx_devices.pluginPci2IsaBridge = thePci2IsaBridge; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePci2IsaBridge, BX_PLUGIN_PCI2ISA); - return(0); // Success -} - - void -libpci2isa_LTX_plugin_fini(void) -{ -} - -bx_pci2isa_c::bx_pci2isa_c(void) -{ - put("P2I"); - settype(PCI2ISALOG); -} - -bx_pci2isa_c::~bx_pci2isa_c(void) -{ - // nothing for now - BX_DEBUG(("Exit.")); -} - - - void -bx_pci2isa_c::init(void) -{ - // called once when bochs initializes - - DEV_register_pci_handlers(this, pci_read_handler, pci_write_handler, - BX_PCI_DEVICE(1,0), "PIIX3 PCI-to-ISA bridge"); - - DEV_register_iowrite_handler(this, write_handler, 0x00B2, "PIIX3 PCI-to-ISA bridge", 1); - DEV_register_iowrite_handler(this, write_handler, 0x00B3, "PIIX3 PCI-to-ISA bridge", 1); - DEV_register_iowrite_handler(this, write_handler, 0x04D0, "PIIX3 PCI-to-ISA bridge", 1); - DEV_register_iowrite_handler(this, write_handler, 0x04D1, "PIIX3 PCI-to-ISA bridge", 1); - DEV_register_iowrite_handler(this, write_handler, 0x0CF9, "PIIX3 PCI-to-ISA bridge", 1); - - DEV_register_ioread_handler(this, read_handler, 0x00B2, "PIIX3 PCI-to-ISA bridge", 1); - DEV_register_ioread_handler(this, read_handler, 0x00B3, "PIIX3 PCI-to-ISA bridge", 1); - DEV_register_ioread_handler(this, read_handler, 0x04D0, "PIIX3 PCI-to-ISA bridge", 1); - DEV_register_ioread_handler(this, read_handler, 0x04D1, "PIIX3 PCI-to-ISA bridge", 1); - DEV_register_ioread_handler(this, read_handler, 0x0CF9, "PIIX3 PCI-to-ISA bridge", 1); - - for (unsigned i=0; i<256; i++) - BX_P2I_THIS s.pci_conf[i] = 0x0; - // readonly registers - BX_P2I_THIS s.pci_conf[0x00] = 0x86; - BX_P2I_THIS s.pci_conf[0x01] = 0x80; - BX_P2I_THIS s.pci_conf[0x02] = 0x00; - BX_P2I_THIS s.pci_conf[0x03] = 0x70; - BX_P2I_THIS s.pci_conf[0x0a] = 0x01; - BX_P2I_THIS s.pci_conf[0x0b] = 0x06; - BX_P2I_THIS s.pci_conf[0x0e] = 0x80; -} - - void -bx_pci2isa_c::reset(unsigned type) -{ - BX_P2I_THIS s.pci_conf[0x04] = 0x07; - BX_P2I_THIS s.pci_conf[0x05] = 0x00; - BX_P2I_THIS s.pci_conf[0x06] = 0x00; - BX_P2I_THIS s.pci_conf[0x07] = 0x02; - BX_P2I_THIS s.pci_conf[0x4c] = 0x4d; - BX_P2I_THIS s.pci_conf[0x4e] = 0x03; - BX_P2I_THIS s.pci_conf[0x4f] = 0x00; - BX_P2I_THIS s.pci_conf[0x60] = 0x80; - BX_P2I_THIS s.pci_conf[0x69] = 0x02; - BX_P2I_THIS s.pci_conf[0x70] = 0x80; - BX_P2I_THIS s.pci_conf[0x76] = 0x0c; - BX_P2I_THIS s.pci_conf[0x77] = 0x0c; - BX_P2I_THIS s.pci_conf[0x78] = 0x02; - BX_P2I_THIS s.pci_conf[0x79] = 0x00; - BX_P2I_THIS s.pci_conf[0x80] = 0x00; - BX_P2I_THIS s.pci_conf[0x82] = 0x00; - BX_P2I_THIS s.pci_conf[0xa0] = 0x08; - BX_P2I_THIS s.pci_conf[0xa0] = 0x08; - BX_P2I_THIS s.pci_conf[0xa2] = 0x00; - BX_P2I_THIS s.pci_conf[0xa3] = 0x00; - BX_P2I_THIS s.pci_conf[0xa4] = 0x00; - BX_P2I_THIS s.pci_conf[0xa5] = 0x00; - BX_P2I_THIS s.pci_conf[0xa6] = 0x00; - BX_P2I_THIS s.pci_conf[0xa7] = 0x00; - BX_P2I_THIS s.pci_conf[0xa8] = 0x0f; - BX_P2I_THIS s.pci_conf[0xaa] = 0x00; - BX_P2I_THIS s.pci_conf[0xab] = 0x00; - BX_P2I_THIS s.pci_conf[0xac] = 0x00; - BX_P2I_THIS s.pci_conf[0xae] = 0x00; - - BX_P2I_THIS s.elcr1 = 0x00; - BX_P2I_THIS s.elcr2 = 0x00; -} - - - - // static IO port read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_pci2isa_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_P2I_SMF - bx_pci2isa_c *class_ptr = (bx_pci2isa_c *) this_ptr; - - return( class_ptr->read(address, io_len) ); -} - - - Bit32u -bx_pci2isa_c::read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_P2I_SMF - - switch (address) { - case 0x00b2: - BX_ERROR(("read: APM command register not supported yet")); - break; - case 0x00b3: - BX_ERROR(("read: APM status register not supported yet")); - break; - case 0x04d0: - return(BX_P2I_THIS s.elcr1); - break; - case 0x04d1: - return(BX_P2I_THIS s.elcr2); - break; - case 0x0cf9: - BX_ERROR(("read: CPU reset register not supported yet")); - break; - } - - return(0xffffffff); -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_pci2isa_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_P2I_SMF - bx_pci2isa_c *class_ptr = (bx_pci2isa_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - - void -bx_pci2isa_c::write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_P2I_SMF - - switch (address) { - case 0x00b2: - BX_ERROR(("write: APM command register not supported yet")); - break; - case 0x00b3: - BX_ERROR(("write: APM status register not supported yet")); - break; - case 0x04d0: - BX_P2I_THIS s.elcr1 = (value & 0xf8); - BX_ERROR(("write: ELCR1 changes have no effect yet")); - break; - case 0x04d1: - BX_P2I_THIS s.elcr2 = (value & 0xde); - BX_ERROR(("write: ELCR2 changes have no effect yet")); - break; - case 0x0cf9: - BX_ERROR(("write: CPU reset register not supported yet")); - break; - } -} - - - // static pci configuration space read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_pci2isa_c::pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len) -{ -#if !BX_USE_P2I_SMF - bx_pci2isa_c *class_ptr = (bx_pci2isa_c *) this_ptr; - - return( class_ptr->pci_read(address, io_len) ); -} - - - Bit32u -bx_pci2isa_c::pci_read(Bit8u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_P2I_SMF - - Bit32u value = 0; - - if (io_len <= 4) { - for (unsigned i=0; ipci_write(address, value, io_len); -} - - void -bx_pci2isa_c::pci_write(Bit8u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_P2I_SMF - - Bit8u value8; - - if (io_len <= 4) { - for (unsigned i=0; i> (i*8)) & 0xFF; - switch (address+i) { - case 0x06: - break; - default: - BX_P2I_THIS s.pci_conf[address+i] = value8; - BX_DEBUG(("PIIX3 PCI-to-ISA write register 0x%02x value 0x%02x", address, - value8)); - } - } - } -} - -#endif /* BX_PCI_SUPPORT */ diff --git a/tools/ioemu/iodev/pci2isa.h b/tools/ioemu/iodev/pci2isa.h deleted file mode 100644 index 1517052d92..0000000000 --- a/tools/ioemu/iodev/pci2isa.h +++ /dev/null @@ -1,63 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pci2isa.h,v 1.4 2002/11/09 20:51:40 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -#if BX_USE_P2I_SMF -# define BX_P2I_SMF static -# define BX_P2I_THIS thePci2IsaBridge-> -#else -# define BX_P2I_SMF -# define BX_P2I_THIS this-> -#endif - - -class bx_pci2isa_c : public bx_devmodel_c { - -public: - bx_pci2isa_c(void); - ~bx_pci2isa_c(void); - virtual void init(void); - virtual void reset(unsigned type); - -private: - - struct { - Bit8u pci_conf[256]; - Bit8u elcr1; - Bit8u elcr2; - } s; - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); - static Bit32u pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len); - static void pci_write_handler(void *this_ptr, Bit8u address, Bit32u value, unsigned io_len); -#if !BX_USE_P2I_SMF - Bit32u read(Bit32u address, unsigned io_len); - void write(Bit32u address, Bit32u value, unsigned io_len); - Bit32u pci_read(Bit8u address, unsigned io_len); - void pci_write(Bit8u address, Bit32u value, unsigned io_len); -#endif - }; diff --git a/tools/ioemu/iodev/pciusb.cc b/tools/ioemu/iodev/pciusb.cc deleted file mode 100644 index e2d4248369..0000000000 --- a/tools/ioemu/iodev/pciusb.cc +++ /dev/null @@ -1,668 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pciusb.cc,v 1.3 2003/02/06 19:09:24 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2003 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// -// Experimental PCI USB adapter -// Benjamin D Lunt (fys@cybertrails.com) coded most of this usb emulation. -// I hope to add to this code to make it more functionable. -// - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_PCI_SUPPORT && BX_PCI_USB_SUPPORT - -#define LOG_THIS theUSBDevice-> - -bx_pciusb_c* theUSBDevice = NULL; - - int -libpciusb_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - theUSBDevice = new bx_pciusb_c (); - bx_devices.pluginPciUSBAdapter = theUSBDevice; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theUSBDevice, BX_PLUGIN_PCIUSB); - return 0; // Success -} - - void -libpciusb_LTX_plugin_fini(void) -{ -} - - -bx_pciusb_c::bx_pciusb_c(void) -{ - put("USB"); - settype(PCIUSBLOG); -} - -bx_pciusb_c::~bx_pciusb_c(void) -{ - // nothing for now - BX_DEBUG(("Exit.")); -} - - - void -bx_pciusb_c::init(void) -{ - // called once when bochs initializes - - if (!bx_options.usb[0].Oenabled->get()) return; - - Bit16u base_ioaddr = bx_options.usb[0].Oioaddr->get(); - Bit8u irq = bx_options.usb[0].Oirq->get(); - - DEV_register_irq(irq, "USB Hub #1"); - BX_USB_THIS hub[0].irq = irq; - - // Call our timer routine every 1mS (1,000uS) - // Continuous and active - BX_USB_THIS hub[0].timer_index = - bx_pc_system.register_timer(this, usb_timer_handler, 1000, 1,1, "usb.timer"); - - for (unsigned addr=base_ioaddr; addr<(unsigned)(base_ioaddr+0x14); addr++) { - BX_DEBUG(("register read/write: 0x%04x", addr)); - DEV_register_ioread_handler(this, read_handler, addr, "USB Hub #1", 7); - DEV_register_iowrite_handler(this, write_handler, addr, "USB Hub #1", 7); - } - BX_USB_THIS hub[0].base_ioaddr = base_ioaddr; - - DEV_register_pci_handlers(this, - pci_read_handler, - pci_write_handler, - BX_PCI_DEVICE(1,2), - "Experimental PCI USB"); - - for (unsigned i=0; i<256; i++) { - BX_USB_THIS hub[0].pci_conf[i] = 0x0; - } - - BX_INFO(("usb1 at 0x%04x-0x%04x irq %d", base_ioaddr, base_ioaddr+0x13, irq)); -} - - void -bx_pciusb_c::reset(unsigned type) -{ - unsigned i; - - static const struct reset_vals_t { - unsigned addr; - unsigned char val; - } reset_vals[] = { - { 0x00, 0x86 }, { 0x01, 0x80 }, // 0x8086 = vendor - { 0x02, 0x20 }, { 0x03, 0x70 }, // 0x7020 = device - { 0x04, 0x05 }, { 0x05, 0x00 }, // command_io - { 0x06, 0x80 }, { 0x07, 0x02 }, // status - { 0x08, 0x01 }, // revision number - { 0x09, 0x00 }, // interface - { 0x0a, 0x03 }, // class_sub USB Host Controller - { 0x0b, 0x0c }, // class_base Serial Bus Controller - { 0x0D, 0x20 }, // bus latency - { 0x0e, 0x00 }, // header_type_generic - // address space 0x20 - 0x23 - { 0x20, ((bx_options.usb[0].Oioaddr->get() & 0xE0) | 0x01) }, - { 0x21, (bx_options.usb[0].Oioaddr->get() >> 8) }, - { 0x22, 0x00 }, { 0x23, 0x00 }, - { 0x3c, bx_options.usb[0].Oirq->get() }, // IRQ - { 0x3d, 0x04 }, // INT - { 0x6a, 0x01 }, // USB clock - { 0xc1, 0x20 } // PIRQ enable - - }; - for (i = 0; i < sizeof(reset_vals) / sizeof(*reset_vals); ++i) { - BX_USB_THIS hub[0].pci_conf[reset_vals[i].addr] = reset_vals[i].val; - } - - // reset locals - BX_USB_THIS global_reset = 0; - - // Put the USB registers into their RESET state - for (i=0; iread(address, io_len) ); -} - - - Bit32u -bx_pciusb_c::read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PCIUSB_SMF - Bit32u val = 0x0; - Bit8u offset,port; - - BX_DEBUG(("register read from address 0x%04x - ", (unsigned) address)); - - offset = address - BX_USB_THIS hub[0].base_ioaddr; - - switch (offset) { - case 0x0C: // Start of Frame Modify - case 0x11: // port0 (high byte read) - case 0x13: // port1 (high byte read) - if (io_len != 1) - BX_PANIC(("io read from port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len)); - break; - case 0x10: // port0 - case 0x12: // port1 - if ((io_len < 1) || (io_len > 2)) - BX_PANIC(("io read from port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len)); - break; - case 0x00: // command register (16-bit) - case 0x02: // status register (16-bit) - case 0x04: // interrupt enable register (1-bit) - case 0x06: // frame number register (16-bit) - if (io_len != 2) - BX_PANIC(("io read from port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len)); - break; - case 0x08: // frame base register (32-bit) - if (io_len != 4) - BX_PANIC(("io read from port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len)); - break; - } - - switch (offset) { - case 0x00: // command register (16-bit) - val = BX_USB_THIS hub[0].usb_command.max_packet_size << 7 - | BX_USB_THIS hub[0].usb_command.configured << 6 - | BX_USB_THIS hub[0].usb_command.debug << 5 - | BX_USB_THIS hub[0].usb_command.resume << 4 - | BX_USB_THIS hub[0].usb_command.suspend << 3 - | BX_USB_THIS hub[0].usb_command.reset << 2 - | BX_USB_THIS hub[0].usb_command.host_reset << 1 - | BX_USB_THIS hub[0].usb_command.schedule; - break; - - case 0x02: // status register (16-bit) - val = BX_USB_THIS hub[0].usb_status.host_halted << 5 - | BX_USB_THIS hub[0].usb_status.host_error << 4 - | BX_USB_THIS hub[0].usb_status.pci_error << 3 - | BX_USB_THIS hub[0].usb_status.resume << 2 - | BX_USB_THIS hub[0].usb_status.error_interrupt << 1 - | BX_USB_THIS hub[0].usb_status.interrupt; - break; - - case 0x04: // interrupt enable register (16-bit) - val = BX_USB_THIS hub[0].usb_enable.short_packet << 3 - | BX_USB_THIS hub[0].usb_enable.on_complete << 2 - | BX_USB_THIS hub[0].usb_enable.resume << 1 - | BX_USB_THIS hub[0].usb_enable.timeout_crc; - break; - - case 0x06: // frame number register (16-bit) - val = BX_USB_THIS hub[0].usb_frame_num.frame_num; - break; - - case 0x08: // frame base register (32-bit) - val = BX_USB_THIS hub[0].usb_frame_base.frame_base; - break; - - case 0x0C: // start of Frame Modify register (8-bit) - val = BX_USB_THIS hub[0].usb_sof.sof_timing; - break; - - case 0x10: // port0 - case 0x12: // port1 - port = (offset & 0x0F) >> 1; - if (port < USB_NUM_PORTS) { - val = BX_USB_THIS hub[0].usb_port[port].suspend << 12 - | BX_USB_THIS hub[0].usb_port[port].reset << 9 - | BX_USB_THIS hub[0].usb_port[port].low_speed << 8 - | 1 << 7 - | BX_USB_THIS hub[0].usb_port[port].resume << 6 - | BX_USB_THIS hub[0].usb_port[port].line_dplus << 5 - | BX_USB_THIS hub[0].usb_port[port].line_dminus << 4 - | BX_USB_THIS hub[0].usb_port[port].able_changed << 3 - | BX_USB_THIS hub[0].usb_port[port].enabled << 2 - | BX_USB_THIS hub[0].usb_port[port].connect_changed << 1 - | BX_USB_THIS hub[0].usb_port[port].status; - break; - } // else fall through to default - - default: - val = 0; // keep compiler happy - BX_PANIC(("unsupported io read from address=0x%04x!", (unsigned) address)); - break; - } - - BX_DEBUG(("val = 0x%08x", (Bit32u) val)); - - return(val); -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_pciusb_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_PCIUSB_SMF - bx_pciusb_c *class_ptr = (bx_pciusb_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - - void -bx_pciusb_c::write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PCIUSB_SMF - Bit8u offset,port; - - BX_DEBUG(("register write to address 0x%04x - ", (unsigned) address)); - - offset = address - BX_USB_THIS hub[0].base_ioaddr; - - switch (offset) { - case 0x0C: // Start of Frame Modify - if (io_len != 1) - BX_PANIC(("io write to port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len)); - break; - case 0x00: // command register (16-bit) - case 0x02: // status register (16-bit) - case 0x04: // interrupt enable register (1-bit) - case 0x06: // frame number register (16-bit) - case 0x10: // port0 - case 0x12: // port1 - if (io_len != 2) - BX_PANIC(("io write to port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len)); - break; - case 0x08: // frame base register (32-bit) - if (io_len != 4) - BX_PANIC(("io write to port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len)); - break; - } - - switch (offset) { - case 0x00: // command register (16-bit) (R/W) - if (value & 0xFF00) - BX_ERROR(("write to command register with bits 15:8 not zero: 0x%04x", value)); - - BX_USB_THIS hub[0].usb_command.max_packet_size = (value & 0x80) ? 1: 0; - BX_USB_THIS hub[0].usb_command.configured = (value & 0x40) ? 1: 0; - BX_USB_THIS hub[0].usb_command.debug = (value & 0x20) ? 1: 0; - BX_USB_THIS hub[0].usb_command.resume = (value & 0x10) ? 1: 0; - BX_USB_THIS hub[0].usb_command.suspend = (value & 0x08) ? 1: 0; - BX_USB_THIS hub[0].usb_command.reset = (value & 0x04) ? 1: 0; - BX_USB_THIS hub[0].usb_command.host_reset = (value & 0x02) ? 1: 0; - BX_USB_THIS hub[0].usb_command.schedule = (value & 0x01) ? 1: 0; - - // If software set the reset bit, we need to set reset bit of each port for 10ms. - if (BX_USB_THIS hub[0].usb_command.reset) - BX_USB_THIS global_reset = 10; - - // If host_reset then reset all registers, etc. - if (BX_USB_THIS hub[0].usb_command.host_reset) - BX_USB_THIS reset(0); - - // If Run/Stop, identify in log and ignore - if (BX_USB_THIS hub[0].usb_command.schedule) - BX_INFO(("Software set Schedule bit in Command register")); - - // If Debug mode set, panic. Not implemented - if (BX_USB_THIS hub[0].usb_command.debug) - BX_PANIC(("Software set DEBUG bit in Command register. Not implemented")); - - break; - - case 0x02: // status register (16-bit) (R/WC) - if (value & 0xFFC0) - BX_ERROR(("write to status register with bits 15:6 not zero: 0x%04x", value)); - - BX_USB_THIS hub[0].usb_status.host_halted = (value & 0x20) ? 0: BX_USB_THIS hub[0].usb_status.host_halted; - BX_USB_THIS hub[0].usb_status.host_error = (value & 0x10) ? 0: BX_USB_THIS hub[0].usb_status.host_error; - BX_USB_THIS hub[0].usb_status.pci_error = (value & 0x08) ? 0: BX_USB_THIS hub[0].usb_status.pci_error; - BX_USB_THIS hub[0].usb_status.resume = (value & 0x04) ? 0: BX_USB_THIS hub[0].usb_status.resume; - BX_USB_THIS hub[0].usb_status.error_interrupt = (value & 0x02) ? 0: BX_USB_THIS hub[0].usb_status.error_interrupt; - BX_USB_THIS hub[0].usb_status.interrupt = (value & 0x01) ? 0: BX_USB_THIS hub[0].usb_status.interrupt; - break; - - case 0x04: // interrupt enable register (16-bit) - if (value & 0xFFF0) - BX_ERROR(("write to interrupt enable register with bits 15:4 not zero: 0x%04x", value)); - - BX_USB_THIS hub[0].usb_enable.short_packet = (value & 0x08) ? 1: 0; - BX_USB_THIS hub[0].usb_enable.on_complete = (value & 0x04) ? 1: 0; - BX_USB_THIS hub[0].usb_enable.resume = (value & 0x02) ? 1: 0; - BX_USB_THIS hub[0].usb_enable.timeout_crc = (value & 0x01) ? 1: 0; - - // For now, we will just ignore these being set since we never raise the IRQ - - break; - - case 0x06: // frame number register (16-bit) - if (value & 0xF800) - BX_ERROR(("write to frame number register with bits 15:11 not zero: 0x%04x", value)); - - if (BX_USB_THIS hub[0].usb_status.host_halted) - BX_USB_THIS hub[0].usb_frame_num.frame_num = value; - else - // ignored by the hardward, but lets report it anyway - BX_ERROR(("write to frame number register with STATUS.HALTED == 0")); - - break; - - case 0x08: // frame base register (32-bit) - if (value & 0xFFF) - BX_PANIC(("write to frame base register with bits 11:0 not zero: 0x%08x", value)); - - BX_USB_THIS hub[0].usb_frame_base.frame_base = value; - break; - - case 0x0C: // start of Frame Modify register (8-bit) - if (value & 0x80) - BX_ERROR(("write to SOF Modify register with bit 7 not zero: 0x%04x", value)); - - BX_USB_THIS hub[0].usb_sof.sof_timing = value; - break; - - case 0x10: // port0 - case 0x12: // port1 - port = (offset & 0x0F) >> 1; - if (port < USB_NUM_PORTS) { - if (value & ((1<<5) | (1<<4) | (1<<0))) - BX_PANIC(("write to one or more read-only bits in port%d register: 0x%04x", port, value)); - if (!(value & (1<<7))) - BX_ERROR(("write to port%d register bit 7 = 0", port)); - if (value & (1<<8)) - BX_INFO(("write to bit 8 in port%d register ignored", port)); - if (value & (1<<2)) - BX_INFO(("port%d enabled ignored. Not implemented", port)); - if ((value & (1<<12)) && BX_USB_THIS hub[0].usb_command.suspend) - BX_ERROR(("write to port%d register bit 12 when in Global-Suspend", port)); - - BX_USB_THIS hub[0].usb_port[port].suspend = (value & (1<<12)) ? 1 : 0; - BX_USB_THIS hub[0].usb_port[port].reset = (value & (1<<9)) ? 1 : 0; - BX_USB_THIS hub[0].usb_port[port].resume = (value & (1<<6)) ? 1 : 0; - BX_USB_THIS hub[0].usb_port[port].able_changed = (value & (1<<3)) ? 0 : BX_USB_THIS hub[0].usb_port[0].able_changed; - BX_USB_THIS hub[0].usb_port[port].enabled = (value & (1<<2)) ? 1 : 0; - BX_USB_THIS hub[0].usb_port[port].connect_changed = (value & (1<<1)) ? 0 : BX_USB_THIS hub[0].usb_port[0].connect_changed; - break; - } - // else fall through to default - - default: - BX_PANIC(("unsupported io write to address=0x%04x!", (unsigned) address)); - break; - } -} - -void bx_pciusb_c::usb_timer_handler(void *this_ptr) -{ - bx_pciusb_c *class_ptr = (bx_pciusb_c *) this_ptr; - class_ptr->usb_timer(); -} - -// Called once every 1ms -void bx_pciusb_c::usb_timer(void) -{ - int i; - - // The Frame Number Register is incremented every 1ms ????????? - // Needs more work and investigation on this. - BX_USB_THIS hub[0].usb_frame_num.frame_num++; - BX_USB_THIS hub[0].usb_frame_num.frame_num &= (1024-1); - - // If the "global reset" bit was set by software, we need - // to set the reset bit in each "active" port for 10ms - if (BX_USB_THIS global_reset) { - for (i=0; ipci_read(address, io_len); -} - - - Bit32u -bx_pciusb_c::pci_read(Bit8u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PCIUSB_SMF - - Bit32u value = 0; - - if (io_len > 4 || io_len == 0) { - BX_ERROR(("Experimental USB PCI read register 0x%02x, len=%u !", - (unsigned) address, (unsigned) io_len)); - return 0xffffffff; - } - - const char* pszName = " "; - switch (address) { - case 0x00: if (io_len == 2) { - pszName = "(vendor id) "; - } else if (io_len == 4) { - pszName = "(vendor + device) "; - } - break; - case 0x04: if (io_len == 2) { - pszName = "(command) "; - } else if (io_len == 4) { - pszName = "(command+status) "; - } - break; - case 0x08: if (io_len == 1) { - pszName = "(revision id) "; - } else if (io_len == 4) { - pszName = "(rev.+class code) "; - } - break; - case 0x0c: pszName = "(cache line size) "; break; - case 0x20: pszName = "(base address) "; break; - case 0x28: pszName = "(cardbus cis) "; break; - case 0x2c: pszName = "(subsys. vendor+) "; break; - case 0x30: pszName = "(rom base) "; break; - case 0x3c: pszName = "(interrupt line+) "; break; - case 0x3d: pszName = "(interrupt pin) "; break; - } - - // This odd code is to display only what bytes actually were read. - char szTmp[9]; - char szTmp2[3]; - szTmp[0] = '\0'; - szTmp2[0] = '\0'; - for (unsigned i=0; ipci_write(address, value, io_len); -} - - void -bx_pciusb_c::pci_write(Bit8u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PCIUSB_SMF - - if (io_len > 4 || io_len == 0) { - BX_ERROR(("Experimental USB PCI write register 0x%02x, len=%u !", - (unsigned) address, (unsigned) io_len)); - return; - } - - // This odd code is to display only what bytes actually were written. - char szTmp[9]; - char szTmp2[3]; - szTmp[0] = '\0'; - szTmp2[0] = '\0'; - for (unsigned i=0; i> (i*8)) & 0xFF; - switch (address+i) { - case 0x20: // Base address - BX_USB_THIS hub[0].pci_conf[address+i] = (value8 & 0xe0) | 0x01; - sprintf(szTmp2, "%02x", (value8 & 0xe0) | 0x01); - break; - case 0x10: // Reserved - case 0x11: // - case 0x12: // - case 0x13: // - case 0x14: // - case 0x15: // - case 0x16: // - case 0x17: // - case 0x18: // - case 0x19: // - case 0x1a: // - case 0x1b: // - case 0x1c: // - case 0x1d: // - case 0x1e: // - case 0x1f: // - case 0x22: // Always 0 - case 0x23: // - case 0x24: // Reserved - case 0x25: // - case 0x26: // - case 0x27: // - case 0x30: // Oh, no, you're not writing to rom_base! - case 0x31: // - case 0x32: // - case 0x33: // - case 0x3d: // - case 0x05: // disallowing write to command hi-byte - case 0x06: // disallowing write to status lo-byte (is that expected?) - strcpy(szTmp2, ".."); - break; - default: - BX_USB_THIS hub[0].pci_conf[address+i] = value8; - sprintf(szTmp2, "%02x", value8); - } - strrev(szTmp2); - strcat(szTmp, szTmp2); - } - strrev(szTmp); - BX_DEBUG(("Experimental USB PCI write register 0x%02x value 0x%s", address, szTmp)); -} - -#endif // BX_PCI_SUPPORT && BX_PCI_USB_SUPPORT diff --git a/tools/ioemu/iodev/pciusb.h b/tools/ioemu/iodev/pciusb.h deleted file mode 100644 index be2532c86f..0000000000 --- a/tools/ioemu/iodev/pciusb.h +++ /dev/null @@ -1,195 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pciusb.h,v 1.1 2003/01/28 16:58:10 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2003 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// Benjamin D Lunt (fys@cybertrails.com) coded most of this usb emulation. -// I hope to add to this code to make it more functionable. -// - -#if BX_USE_PCIUSB_SMF -# define BX_USB_THIS theUSBDevice-> -#else -# define BX_USB_THIS this-> -#endif - -#define BX_USB_MAXDEV 1 -#define BX_USB_CONFDEV 1 /* only 1 USB hub currently */ - -#define USB_NUM_PORTS 2 /* UHCI supports 2 ports per root hub */ - -typedef struct { - - Bit16u base_ioaddr; - Bit8u irq; - int timer_index; - - // Registers - // Base + 0x00 Command register - // Base + 0x02 Status register - // Base + 0x04 Interrupt Enable register - // Base + 0x06 Frame Number register - // Base + 0x08 Frame Base Register (32-bit) - // Base + 0x0C Start of Frame Modify register - // Base + 0x0D - // Base + 0x0E - // Base + 0x0F - // Base + 0x10 Eight(?) 16-bit ports (one for each port on hub) - - // Bit reps of registers above - // Command Register - // Bits 15-8 are reserved - // Bit 7 = Maximum packet size - // Bit 6 = Host Controller has been configured (set by software) - // Bit 5 = software debug mode - // Bit 4 = force global resume - // Bit 3 = enter global suspend mode - // Bit 2 = global reset - // Bit 1 = host controller reset - // Bit 0 = run/stop schedule - struct { - bx_bool max_packet_size; //(bit 7) 0 = 32 bytes, 1 = 64 bytes - bx_bool configured; //(bit 6) - bx_bool debug; //(bit 5) - bx_bool resume; //(bit 4) - bx_bool suspend; //(bit 3) - bx_bool reset; //(bit 2) - bx_bool host_reset; //(bit 1) - bx_bool schedule; //(bit 0) 0 = Stop, 1 = Run - } usb_command; - - // Status Register - // Bits 15-6 are reserved - // Bit 5 = Host controller halted - // Bit 4 = Host controller process error - // Bit 3 = PCI Bus error - // Bit 2 = resume received - // Bit 1 = USB error interrupt - // Bit 0 = USB interrupt - struct { - bx_bool host_halted; //(bit 5) - bx_bool host_error; //(bit 4) - bx_bool pci_error; //(bit 3) - bx_bool resume; //(bit 2) - bx_bool error_interrupt; //(bit 1) - bx_bool interrupt; //(bit 0) - } usb_status; - - // Interrupt Enable Register - // Bits 15-4 are reserved - // Bit 3 = enable short packet interrupts - // Bit 2 = enable interrupt On Complete - // Bit 1 = enable resume - // Bit 0 = enable timeout/crc - struct { - bx_bool short_packet; //(bit 3) - bx_bool on_complete; //(bit 2) - bx_bool resume; //(bit 1) - bx_bool timeout_crc; //(bit 0) - } usb_enable; - - // Frame Number Register - // Bits 15-11 are reserved - // Bits 10-0 Frame List Current Index/Frame Number - struct { - Bit16u frame_num; - } usb_frame_num; - - // Frame List Base Address Register - // Bits 31-12 Base - // Bits 11-0 *must* be zeros when written to - struct { - Bit32u frame_base; - } usb_frame_base; - - // Start of Frame Modify Register - // Bit 7 reserved - // Bits 6-0 SOF timing value (default 64) - // SOF cycle time equals 11936+timing value - struct { - Bit8u sof_timing; - } usb_sof; - - // Port Register (0-1) - // Bits 15-13 are reserved - // Bit 12 suspend port - // Bit 11-10 are reserved - // Bit 9 port in reset state - // Bit 8 low-speed device is attached (read-only) - // Bit 7 reserved - // Bit 6 resume detected (read-only) - // Bit 5 line-status D+ (read-only) - // Bit 4 line-status D- (read-only) - // Bit 3 port enabled/disable status has changed - // (write 1 to this bit to clear it) - // Bit 2 port is enabled - // Bit 1 connect status has changed - // (write 1 to this bit to clear it) - // Bit 0 current connect status (read-only) - // Can only write in WORD sizes (Read in byte sizes???) - struct { - bx_bool suspend; - bx_bool reset; - bx_bool low_speed; - bx_bool resume; - bx_bool line_dplus; - bx_bool line_dminus; - bx_bool able_changed; - bx_bool enabled; - bx_bool connect_changed; - bx_bool status; - } usb_port[USB_NUM_PORTS]; - - Bit8u pci_conf[256]; - -} bx_usb_t; - - -class bx_pciusb_c : public bx_devmodel_c -{ -public: - bx_pciusb_c(void); - ~bx_pciusb_c(void); - virtual void init(void); - virtual void reset(unsigned type); - -private: - - bx_usb_t hub[BX_USB_MAXDEV]; - Bit8u global_reset; - - static void usb_timer_handler(void *); - void usb_timer(void); - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); - static Bit32u pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len); - static void pci_write_handler(void *this_ptr, Bit8u address, Bit32u value, unsigned io_len); -#if !BX_USE_PCIUSB_SMF - Bit32u read(Bit32u address, unsigned io_len); - void write(Bit32u address, Bit32u value, unsigned io_len); - Bit32u pci_read(Bit8u address, unsigned io_len); - void pci_write(Bit8u address, Bit32u value, unsigned io_len); -#endif -}; diff --git a/tools/ioemu/iodev/pcivga.cc b/tools/ioemu/iodev/pcivga.cc deleted file mode 100644 index 4d999be74d..0000000000 --- a/tools/ioemu/iodev/pcivga.cc +++ /dev/null @@ -1,248 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pcivga.cc,v 1.2 2003/01/23 19:31:28 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002,2003 Mike Nordell -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// -// Experimental PCI VGA adapter -// - -// Note: This "driver" was created for the SOLE PURPOSE of getting BeOS -// to boot. It currently does NOTHING more than presenting a generic VGA -// device on the PCI bus. ALL gfx in/out-put is still handled by the VGA code. -// Furthermore, almost all of the PCI registers are currently acting like RAM. - - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if BX_PCI_SUPPORT && BX_PCI_VGA_SUPPORT - -#define LOG_THIS thePciVgaAdapter-> - -bx_pcivga_c* thePciVgaAdapter = 0; - - int -libpcivga_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - thePciVgaAdapter = new bx_pcivga_c (); - bx_devices.pluginPciVgaAdapter = thePciVgaAdapter; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePciVgaAdapter, BX_PLUGIN_PCIVGA); - return 0; // Success -} - - void -libpcivga_LTX_plugin_fini(void) -{ -} - - -bx_pcivga_c::bx_pcivga_c(void) -{ - put("PCIVGA"); - settype(PCIVGALOG); -} - -bx_pcivga_c::~bx_pcivga_c(void) -{ - // nothing for now - BX_DEBUG(("Exit.")); -} - - - void -bx_pcivga_c::init(void) -{ - // called once when bochs initializes - - DEV_register_pci_handlers(this, - pci_read_handler, - pci_write_handler, - BX_PCI_DEVICE(2,0), - "Experimental PCI VGA"); - - for (unsigned i=0; i<256; i++) { - BX_PCIVGA_THIS s.pci_conf[i] = 0x0; - } - - // readonly registers - static const struct init_vals_t { - unsigned addr; - unsigned char val; - } init_vals[] = { - // Note that the values for vendor and device id are selected at random! - // There might actually be "real" values for "experimental" vendor and - // device that should be used! - { 0x00, 0x34 }, { 0x01, 0x12 }, // 0x1234 - experimental vendor - { 0x02, 0x11 }, { 0x03, 0x11 }, // 0x1111 - experimental device - { 0x0a, 0x00 }, // class_sub VGA controller - { 0x0b, 0x03 }, // class_base display - { 0x0e, 0x00 } // header_type_generic - }; - for (unsigned i = 0; i < sizeof(init_vals) / sizeof(*init_vals); ++i) { - BX_PCIVGA_THIS s.pci_conf[init_vals[i].addr] = init_vals[i].val; - } -} - - void -bx_pcivga_c::reset(unsigned type) -{ - static const struct reset_vals_t { - unsigned addr; - unsigned char val; - } reset_vals[] = { - { 0x04, 0x01 }, { 0x05, 0x00 }, // command_io - { 0x06, 0x00 }, { 0x07, 0x02 } // status_devsel_medium - }; - for (unsigned i = 0; i < sizeof(reset_vals) / sizeof(*reset_vals); ++i) { - BX_PCIVGA_THIS s.pci_conf[reset_vals[i].addr] = reset_vals[i].val; - } -} - - - // static pci configuration space read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_pcivga_c::pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len) -{ -#if !BX_USE_PCIVGA_SMF - bx_pcivga_c *class_ptr = (bx_pcivga_c *) this_ptr; - - return class_ptr->pci_read(address, io_len); -} - - - Bit32u -bx_pcivga_c::pci_read(Bit8u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PCIVGA_SMF - - Bit32u value = 0; - - if (io_len > 4 || io_len == 0) { - BX_DEBUG(("Experimental PCIVGA read register 0x%02x, len=%u !", - (unsigned) address, (unsigned) io_len)); - return 0xffffffff; - } - - const char* pszName = " "; - switch (address) { - case 0x00: if (io_len == 2) { - pszName = "(vendor id) "; - } else if (io_len == 4) { - pszName = "(vendor + device) "; - } - break; - case 0x04: if (io_len == 2) { - pszName = "(command) "; - } else if (io_len == 4) { - pszName = "(command+status) "; - } - break; - case 0x08: if (io_len == 1) { - pszName = "(revision id) "; - } else if (io_len == 4) { - pszName = "(rev.+class code) "; - } - break; - case 0x0c: pszName = "(cache line size) "; break; - case 0x28: pszName = "(cardbus cis) "; break; - case 0x2c: pszName = "(subsys. vendor+) "; break; - case 0x30: pszName = "(rom base) "; break; - case 0x3c: pszName = "(interrupt line+) "; break; - case 0x3d: pszName = "(interrupt pin) "; break; - } - - // This odd code is to display only what bytes actually were read. - char szTmp[9]; - char szTmp2[3]; - szTmp[0] = '\0'; - szTmp2[0] = '\0'; - for (unsigned i=0; ipci_write(address, value, io_len); -} - - void -bx_pcivga_c::pci_write(Bit8u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PCIVGA_SMF - - if (io_len > 4 || io_len == 0) { - BX_DEBUG(("Experimental PCIVGA write register 0x%02x, len=%u !", - (unsigned) address, (unsigned) io_len)); - return; - } - - // This odd code is to display only what bytes actually were written. - char szTmp[9]; - char szTmp2[3]; - szTmp[0] = '\0'; - szTmp2[0] = '\0'; - for (unsigned i=0; i> (i*8)) & 0xFF; - switch (address+i) { - case 0x30: // Oh, no, you're not writing to rom_base! - case 0x31: // - case 0x32: // - case 0x33: // - case 0x04: // disallowing write to command - case 0x06: // disallowing write to status lo-byte (is that expected?) - strcpy(szTmp2, ".."); - break; - default: - BX_PCIVGA_THIS s.pci_conf[address+i] = value8; - sprintf(szTmp2, "%02x", value8); - } - strrev(szTmp2); - strcat(szTmp, szTmp2); - } - strrev(szTmp); - BX_DEBUG(("Experimental PCIVGA write register 0x%02x value 0x%s", address, szTmp)); -} - -#endif // BX_PCI_SUPPORT && BX_PCI_VGA_SUPPORT diff --git a/tools/ioemu/iodev/pcivga.h b/tools/ioemu/iodev/pcivga.h deleted file mode 100644 index 15bd986a09..0000000000 --- a/tools/ioemu/iodev/pcivga.h +++ /dev/null @@ -1,48 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pcivga.h,v 1.3 2003/01/27 21:11:55 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002,2003 Mike Nordell -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -#if BX_USE_PCIVGA_SMF -# define BX_PCIVGA_THIS thePciVgaAdapter-> -#else -# define BX_PCIVGA_THIS this-> -#endif - - -class bx_pcivga_c : public bx_devmodel_c -{ -public: - bx_pcivga_c(void); - ~bx_pcivga_c(void); - virtual void init(void); - virtual void reset(unsigned type); - -private: - - struct { - Bit8u pci_conf[256]; - } s; - - static Bit32u pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len); - static void pci_write_handler(void *this_ptr, Bit8u address, Bit32u value, unsigned io_len); -#if !BX_USE_PCIVGA_SMF - Bit32u pci_read(Bit8u address, unsigned io_len); - void pci_write(Bit8u address, Bit32u value, unsigned io_len); -#endif -}; diff --git a/tools/ioemu/iodev/pic.cc b/tools/ioemu/iodev/pic.cc deleted file mode 100644 index f4455508b6..0000000000 --- a/tools/ioemu/iodev/pic.cc +++ /dev/null @@ -1,887 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pic.cc,v 1.33 2003/08/05 09:19:36 akrisak Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" - -#define LOG_THIS thePic-> - - - -bx_pic_c *thePic = NULL; - - int -libpic_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - thePic = new bx_pic_c (); - bx_devices.pluginPicDevice = thePic; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePic, BX_PLUGIN_PIC); - return(0); // Success -} - - void -libpic_LTX_plugin_fini(void) -{ -} - - -bx_pic_c::bx_pic_c(void) -{ - put("PIC"); - settype(PICLOG); -} - -bx_pic_c::~bx_pic_c(void) -{ - // nothing for now -} - - - void -bx_pic_c::init(void) -{ - /* 8259 PIC (Programmable Interrupt Controller) */ - DEV_register_ioread_handler(this, read_handler, 0x0020, "8259 PIC", 1); - DEV_register_ioread_handler(this, read_handler, 0x0021, "8259 PIC", 1); - DEV_register_ioread_handler(this, read_handler, 0x00A0, "8259 PIC", 1); - DEV_register_ioread_handler(this, read_handler, 0x00A1, "8259 PIC", 1); - - DEV_register_iowrite_handler(this, write_handler, 0x0020, "8259 PIC", 1); - DEV_register_iowrite_handler(this, write_handler, 0x0021, "8259 PIC", 1); - DEV_register_iowrite_handler(this, write_handler, 0x00A0, "8259 PIC", 1); - DEV_register_iowrite_handler(this, write_handler, 0x00A1, "8259 PIC", 1); - - - BX_PIC_THIS s.master_pic.single_PIC = 0; - BX_PIC_THIS s.master_pic.interrupt_offset = 0x08; /* IRQ0 = INT 0x08 */ - /* slave PIC connected to IRQ2 of master */ - BX_PIC_THIS s.master_pic.u.slave_connect_mask = 0x04; - BX_PIC_THIS s.master_pic.sfnm = 0; /* normal nested mode */ - BX_PIC_THIS s.master_pic.buffered_mode = 0; /* unbuffered mode */ - BX_PIC_THIS s.master_pic.master_slave = 0; /* no meaning, buffered_mode=0 */ - BX_PIC_THIS s.master_pic.auto_eoi = 0; /* manual EOI from CPU */ - BX_PIC_THIS s.master_pic.imr = 0xFF; /* all IRQ's initially masked */ - BX_PIC_THIS s.master_pic.isr = 0x00; /* no IRQ's in service */ - BX_PIC_THIS s.master_pic.irr = 0x00; /* no IRQ's requested */ - BX_PIC_THIS s.master_pic.read_reg_select = 0; /* IRR */ - BX_PIC_THIS s.master_pic.irq = 0; - BX_PIC_THIS s.master_pic.INT = 0; - BX_PIC_THIS s.master_pic.init.in_init = 0; - BX_PIC_THIS s.master_pic.init.requires_4 = 0; - BX_PIC_THIS s.master_pic.init.byte_expected = 0; - BX_PIC_THIS s.master_pic.special_mask = 0; - BX_PIC_THIS s.master_pic.lowest_priority = 7; - BX_PIC_THIS s.master_pic.polled = 0; - BX_PIC_THIS s.master_pic.rotate_on_autoeoi = 0; - - BX_PIC_THIS s.slave_pic.single_PIC = 0; - BX_PIC_THIS s.slave_pic.interrupt_offset = 0x70; /* IRQ8 = INT 0x70 */ - BX_PIC_THIS s.slave_pic.u.slave_id = 0x02; /* slave PIC connected to IRQ2 of master */ - BX_PIC_THIS s.slave_pic.sfnm = 0; /* normal nested mode */ - BX_PIC_THIS s.slave_pic.buffered_mode = 0; /* unbuffered mode */ - BX_PIC_THIS s.slave_pic.master_slave = 0; /* no meaning, buffered_mode=0 */ - BX_PIC_THIS s.slave_pic.auto_eoi = 0; /* manual EOI from CPU */ - BX_PIC_THIS s.slave_pic.imr = 0xFF; /* all IRQ's initially masked */ - BX_PIC_THIS s.slave_pic.isr = 0x00; /* no IRQ's in service */ - BX_PIC_THIS s.slave_pic.irr = 0x00; /* no IRQ's requested */ - BX_PIC_THIS s.slave_pic.read_reg_select = 0; /* IRR */ - BX_PIC_THIS s.slave_pic.irq = 0; - BX_PIC_THIS s.slave_pic.INT = 0; - BX_PIC_THIS s.slave_pic.init.in_init = 0; - BX_PIC_THIS s.slave_pic.init.requires_4 = 0; - BX_PIC_THIS s.slave_pic.init.byte_expected = 0; - BX_PIC_THIS s.slave_pic.special_mask = 0; - BX_PIC_THIS s.slave_pic.lowest_priority = 7; - BX_PIC_THIS s.slave_pic.polled = 0; - BX_PIC_THIS s.slave_pic.rotate_on_autoeoi = 0; - - for (unsigned i=0; i<8; i++) { /* all IRQ lines low */ - BX_PIC_THIS s.master_pic.IRQ_line[i] = 0; - BX_PIC_THIS s.slave_pic.IRQ_line[i] = 0; - } -} - - void -bx_pic_c::reset(unsigned type) -{ -} - - // static IO port read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_pic_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_PIC_SMF - bx_pic_c *class_ptr = (bx_pic_c *) this_ptr; - - return( class_ptr->read(address, io_len) ); -} - - - - Bit32u -bx_pic_c::read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PIC_SMF - - BX_DEBUG(("IO read from %04x", (unsigned) address)); - - /* - 8259A PIC - */ - - if((address == 0x20 || address == 0x21) && BX_PIC_THIS s.master_pic.polled) { - // In polled mode. Treat this as an interrupt acknowledge - clear_highest_interrupt(& BX_PIC_THIS s.master_pic); - BX_PIC_THIS s.master_pic.polled = 0; - service_master_pic(); - return io_len==1?BX_PIC_THIS s.master_pic.irq:(BX_PIC_THIS s.master_pic.irq)<<8|(BX_PIC_THIS s.master_pic.irq); // Return the current irq requested - } - - if((address == 0xa0 || address == 0xa1) && BX_PIC_THIS s.slave_pic.polled) { - // In polled mode. Treat this as an interrupt acknowledge - clear_highest_interrupt(& BX_PIC_THIS s.slave_pic); - BX_PIC_THIS s.slave_pic.polled = 0; - service_slave_pic(); - return io_len==1?BX_PIC_THIS s.slave_pic.irq:(BX_PIC_THIS s.slave_pic.irq)<<8|(BX_PIC_THIS s.slave_pic.irq); // Return the current irq requested - } - - - switch (address) { - case 0x20: - if (BX_PIC_THIS s.master_pic.read_reg_select) { /* ISR */ - BX_DEBUG(("read master ISR = %02x", - (unsigned) BX_PIC_THIS s.master_pic.isr)); - return(BX_PIC_THIS s.master_pic.isr); - } - else { /* IRR */ - BX_DEBUG(("read master IRR = %02x", - (unsigned) BX_PIC_THIS s.master_pic.irr)); - return(BX_PIC_THIS s.master_pic.irr); - } - break; - case 0x21: - BX_DEBUG(("read master IMR = %02x", - (unsigned) BX_PIC_THIS s.master_pic.imr)); - return(BX_PIC_THIS s.master_pic.imr); - break; - case 0xA0: - if (BX_PIC_THIS s.slave_pic.read_reg_select) { /* ISR */ - BX_DEBUG(("read slave ISR = %02x", - (unsigned) BX_PIC_THIS s.slave_pic.isr)); - return(BX_PIC_THIS s.slave_pic.isr); - } - else { /* IRR */ - BX_DEBUG(("read slave IRR = %02x", - (unsigned) BX_PIC_THIS s.slave_pic.irr)); - return(BX_PIC_THIS s.slave_pic.irr); - } - break; - case 0xA1: - BX_DEBUG(("read slave IMR = %02x", - (unsigned) BX_PIC_THIS s.slave_pic.imr)); - return(BX_PIC_THIS s.slave_pic.imr); - break; - } - - BX_PANIC(("io read to address %04x", (unsigned) address)); - return(0); /* default if not found above */ -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_pic_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_PIC_SMF - bx_pic_c *class_ptr = (bx_pic_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - - void -bx_pic_c::write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PIC_SMF - - BX_DEBUG(("IO write to %04x = %02x", (unsigned) address, (unsigned) value)); - - /* - 8259A PIC - */ - - switch (address) { - case 0x20: - if (value & 0x10) { /* initialization command 1 */ - BX_DEBUG(("master: init command 1 found")); - BX_DEBUG((" requires 4 = %u", (unsigned) (value & 0x01) )); - BX_DEBUG((" cascade mode: [0=cascade,1=single] %u", - (unsigned) ((value & 0x02) >> 1))); - BX_PIC_THIS s.master_pic.init.in_init = 1; - BX_PIC_THIS s.master_pic.init.requires_4 = (value & 0x01); - BX_PIC_THIS s.master_pic.init.byte_expected = 2; /* operation command 2 */ - BX_PIC_THIS s.master_pic.imr = 0x00; /* clear the irq mask register */ - BX_PIC_THIS s.master_pic.isr = 0x00; /* no IRQ's in service */ - BX_PIC_THIS s.master_pic.irr = 0x00; /* no IRQ's requested */ - BX_PIC_THIS s.master_pic.lowest_priority = 7; - BX_PIC_THIS s.master_pic.INT = 0; /* reprogramming clears previous INTR request */ - BX_PIC_THIS s.master_pic.auto_eoi = 0; - BX_PIC_THIS s.master_pic.rotate_on_autoeoi = 0; - if (value & 0x02) - BX_PANIC(("master: ICW1: single mode not supported")); - if (value & 0x08) { - BX_PANIC(("master: ICW1: level sensitive mode not supported")); - } - else { - BX_DEBUG(("master: ICW1: edge triggered mode selected")); - } - BX_SET_INTR(0); - return; - } - - if ( (value & 0x18) == 0x08 ) { /* OCW3 */ - Bit8u special_mask, poll, read_op; - - special_mask = (value & 0x60) >> 5; - poll = (value & 0x04) >> 2; - read_op = (value & 0x03); - if (poll) { - BX_PIC_THIS s.master_pic.polled = 1; - return; - } - if (read_op == 0x02) /* read IRR */ - BX_PIC_THIS s.master_pic.read_reg_select = 0; - else if (read_op == 0x03) /* read ISR */ - BX_PIC_THIS s.master_pic.read_reg_select = 1; - if (special_mask == 0x02) { /* cancel special mask */ - BX_PIC_THIS s.master_pic.special_mask = 0; - } - else if (special_mask == 0x03) { /* set specific mask */ - BX_PIC_THIS s.master_pic.special_mask = 1; - service_master_pic(); - } - return; - } - - /* OCW2 */ - switch (value) { - case 0x00: // Rotate in auto eoi mode clear - case 0x80: // Rotate in auto eoi mode set - BX_PIC_THIS s.master_pic.rotate_on_autoeoi = (value != 0); - break; - case 0x0A: /* select read interrupt request register */ - BX_PIC_THIS s.master_pic.read_reg_select = 0; - break; - case 0x0B: /* select read interrupt in-service register */ - BX_PIC_THIS s.master_pic.read_reg_select = 1; - break; - - case 0xA0: // Rotate on non-specific end of interrupt - case 0x20: /* end of interrupt command */ - - clear_highest_interrupt(& BX_PIC_THIS s.master_pic); - - if(value == 0xA0) {// Rotate in Auto-EOI mode - BX_PIC_THIS s.master_pic.lowest_priority ++; - if(BX_PIC_THIS s.master_pic.lowest_priority > 7) - BX_PIC_THIS s.master_pic.lowest_priority = 0; - } - - service_master_pic(); - break; - - case 0x40: // Intel PIC spec-sheet seems to indicate this should be ignored - BX_INFO(("IRQ no-op")); - break; - - case 0x60: /* specific EOI 0 */ - case 0x61: /* specific EOI 1 */ - case 0x62: /* specific EOI 2 */ - case 0x63: /* specific EOI 3 */ - case 0x64: /* specific EOI 4 */ - case 0x65: /* specific EOI 5 */ - case 0x66: /* specific EOI 6 */ - case 0x67: /* specific EOI 7 */ - BX_PIC_THIS s.master_pic.isr &= ~(1 << (value-0x60)); - service_master_pic(); - break; - - // IRQ lowest priority commands - case 0xC0: // 0 7 6 5 4 3 2 1 - case 0xC1: // 1 0 7 6 5 4 3 2 - case 0xC2: // 2 1 0 7 6 5 4 3 - case 0xC3: // 3 2 1 0 7 6 5 4 - case 0xC4: // 4 3 2 1 0 7 6 5 - case 0xC5: // 5 4 3 2 1 0 7 6 - case 0xC6: // 6 5 4 3 2 1 0 7 - case 0xC7: // 7 6 5 4 3 2 1 0 - BX_INFO(("IRQ lowest command 0x%x", value)); - BX_PIC_THIS s.master_pic.lowest_priority = value - 0xC0; - break; - - case 0xE0: // specific EOI and rotate 0 - case 0xE1: // specific EOI and rotate 1 - case 0xE2: // specific EOI and rotate 2 - case 0xE3: // specific EOI and rotate 3 - case 0xE4: // specific EOI and rotate 4 - case 0xE5: // specific EOI and rotate 5 - case 0xE6: // specific EOI and rotate 6 - case 0xE7: // specific EOI and rotate 7 - BX_PIC_THIS s.master_pic.isr &= ~(1 << (value-0xE0)); - BX_PIC_THIS s.master_pic.lowest_priority = (value - 0xE0); - service_master_pic(); - - break; - - default: - BX_PANIC(("write to port 20h = %02x", value)); - } /* switch (value) */ - break; - - case 0x21: - /* initialization mode operation */ - if (BX_PIC_THIS s.master_pic.init.in_init) { - switch (BX_PIC_THIS s.master_pic.init.byte_expected) { - case 2: - BX_PIC_THIS s.master_pic.interrupt_offset = value & 0xf8; - BX_PIC_THIS s.master_pic.init.byte_expected = 3; - BX_DEBUG(("master: init command 2 = %02x", (unsigned) value)); - BX_DEBUG((" offset = INT %02x", - BX_PIC_THIS s.master_pic.interrupt_offset)); - return; - break; - case 3: - BX_DEBUG(("master: init command 3 = %02x", (unsigned) value)); - if (BX_PIC_THIS s.master_pic.init.requires_4) { - BX_PIC_THIS s.master_pic.init.byte_expected = 4; - } - else { - BX_PIC_THIS s.master_pic.init.in_init = 0; - } - return; - break; - case 4: - BX_DEBUG(("master: init command 4 = %02x", (unsigned) value)); - if (value & 0x02) { - BX_DEBUG((" auto EOI")); - BX_PIC_THIS s.master_pic.auto_eoi = 1; - } - else { - BX_DEBUG(("normal EOI interrupt")); - BX_PIC_THIS s.master_pic.auto_eoi = 0; - } - if (value & 0x01) { - BX_DEBUG((" 80x86 mode")); - } else - BX_PANIC((" not 80x86 mode")); - BX_PIC_THIS s.master_pic.init.in_init = 0; - return; - break; - default: - BX_PANIC(("master expecting bad init command")); - } - } - - /* normal operation */ - BX_DEBUG(("setting master pic IMR to %02x", value)); - BX_PIC_THIS s.master_pic.imr = value; - service_master_pic(); - return; - break; - - case 0xA0: - if (value & 0x10) { /* initialization command 1 */ - BX_DEBUG(("slave: init command 1 found")); - BX_DEBUG((" requires 4 = %u", - (unsigned) (value & 0x01) )); - BX_DEBUG((" cascade mode: [0=cascade,1=single] %u", - (unsigned) ((value & 0x02) >> 1))); - BX_PIC_THIS s.slave_pic.init.in_init = 1; - BX_PIC_THIS s.slave_pic.init.requires_4 = (value & 0x01); - BX_PIC_THIS s.slave_pic.init.byte_expected = 2; /* operation command 2 */ - BX_PIC_THIS s.slave_pic.imr = 0x00; /* clear irq mask */ - BX_PIC_THIS s.slave_pic.isr = 0x00; /* no IRQ's in service */ - BX_PIC_THIS s.slave_pic.irr = 0x00; /* no IRQ's requested */ - BX_PIC_THIS s.slave_pic.lowest_priority = 7; - BX_PIC_THIS s.slave_pic.INT = 0; /* reprogramming clears previous INTR request */ - BX_PIC_THIS s.slave_pic.auto_eoi = 0; - BX_PIC_THIS s.slave_pic.rotate_on_autoeoi = 0; - if (value & 0x02) - BX_PANIC(("slave: ICW1: single mode not supported")); - if (value & 0x08) { - BX_PANIC(("slave: ICW1: level sensitive mode not supported")); - } - else { - BX_DEBUG(("slave: ICW1: edge triggered mode selected")); - } - return; - } - - if ( (value & 0x18) == 0x08 ) { /* OCW3 */ - Bit8u special_mask, poll, read_op; - - special_mask = (value & 0x60) >> 5; - poll = (value & 0x04) >> 2; - read_op = (value & 0x03); - if (poll) { - BX_PIC_THIS s.slave_pic.polled = 1; - return; - } - if (read_op == 0x02) /* read IRR */ - BX_PIC_THIS s.slave_pic.read_reg_select = 0; - else if (read_op == 0x03) /* read ISR */ - BX_PIC_THIS s.slave_pic.read_reg_select = 1; - if (special_mask == 0x02) { /* cancel special mask */ - BX_PIC_THIS s.slave_pic.special_mask = 0; - } - else if (special_mask == 0x03) { /* set specific mask */ - BX_PIC_THIS s.slave_pic.special_mask = 1; - service_slave_pic(); - } - return; - } - - switch (value) { - case 0x00: // Rotate in auto eoi mode clear - case 0x80: // Rotate in auto eoi mode set - BX_PIC_THIS s.slave_pic.rotate_on_autoeoi = (value != 0); - break; - - case 0x0A: /* select read interrupt request register */ - BX_PIC_THIS s.slave_pic.read_reg_select = 0; - break; - case 0x0B: /* select read interrupt in-service register */ - BX_PIC_THIS s.slave_pic.read_reg_select = 1; - break; - - case 0xA0: // Rotate on non-specific end of interrupt - case 0x20: /* end of interrupt command */ - - clear_highest_interrupt(& BX_PIC_THIS s.slave_pic); - - if(value == 0xA0) {// Rotate in Auto-EOI mode - BX_PIC_THIS s.slave_pic.lowest_priority ++; - if(BX_PIC_THIS s.slave_pic.lowest_priority > 7) - BX_PIC_THIS s.slave_pic.lowest_priority = 0; - } - - service_slave_pic(); - break; - - case 0x40: // Intel PIC spec-sheet seems to indicate this should be ignored - BX_INFO(("IRQ no-op")); - break; - - case 0x60: /* specific EOI 0 */ - case 0x61: /* specific EOI 1 */ - case 0x62: /* specific EOI 2 */ - case 0x63: /* specific EOI 3 */ - case 0x64: /* specific EOI 4 */ - case 0x65: /* specific EOI 5 */ - case 0x66: /* specific EOI 6 */ - case 0x67: /* specific EOI 7 */ - BX_PIC_THIS s.slave_pic.isr &= ~(1 << (value-0x60)); - service_slave_pic(); - break; - - // IRQ lowest priority commands - case 0xC0: // 0 7 6 5 4 3 2 1 - case 0xC1: // 1 0 7 6 5 4 3 2 - case 0xC2: // 2 1 0 7 6 5 4 3 - case 0xC3: // 3 2 1 0 7 6 5 4 - case 0xC4: // 4 3 2 1 0 7 6 5 - case 0xC5: // 5 4 3 2 1 0 7 6 - case 0xC6: // 6 5 4 3 2 1 0 7 - case 0xC7: // 7 6 5 4 3 2 1 0 - BX_INFO(("IRQ lowest command 0x%x", value)); - BX_PIC_THIS s.slave_pic.lowest_priority = value - 0xC0; - break; - - case 0xE0: // specific EOI and rotate 0 - case 0xE1: // specific EOI and rotate 1 - case 0xE2: // specific EOI and rotate 2 - case 0xE3: // specific EOI and rotate 3 - case 0xE4: // specific EOI and rotate 4 - case 0xE5: // specific EOI and rotate 5 - case 0xE6: // specific EOI and rotate 6 - case 0xE7: // specific EOI and rotate 7 - BX_PIC_THIS s.slave_pic.isr &= ~(1 << (value-0xE0)); - BX_PIC_THIS s.slave_pic.lowest_priority = (value - 0xE0); - service_slave_pic(); - - break; - - default: - BX_PANIC(("write to port A0h = %02x", value)); - } /* switch (value) */ - break; - - case 0xA1: - /* initialization mode operation */ - if (BX_PIC_THIS s.slave_pic.init.in_init) { - switch (BX_PIC_THIS s.slave_pic.init.byte_expected) { - case 2: - BX_PIC_THIS s.slave_pic.interrupt_offset = value & 0xf8; - BX_PIC_THIS s.slave_pic.init.byte_expected = 3; - BX_DEBUG(("slave: init command 2 = %02x", (unsigned) value)); - BX_DEBUG((" offset = INT %02x", - BX_PIC_THIS s.slave_pic.interrupt_offset)); - return; - break; - case 3: - BX_DEBUG(("slave: init command 3 = %02x", (unsigned) value)); - if (BX_PIC_THIS s.slave_pic.init.requires_4) { - BX_PIC_THIS s.slave_pic.init.byte_expected = 4; - } else { - BX_PIC_THIS s.slave_pic.init.in_init = 0; - } - return; - break; - case 4: - BX_DEBUG(("slave: init command 4 = %02x", (unsigned) value)); - if (value & 0x02) { - BX_DEBUG((" auto EOI")); - BX_PIC_THIS s.slave_pic.auto_eoi = 1; - } - else { - BX_DEBUG(("normal EOI interrupt")); - BX_PIC_THIS s.slave_pic.auto_eoi = 0; - } - if (value & 0x01) { - BX_DEBUG((" 80x86 mode")); - } else - BX_PANIC((" not 80x86 mode")); - BX_PIC_THIS s.slave_pic.init.in_init = 0; - return; - break; - default: - BX_PANIC(("slave: expecting bad init command")); - } - } - - /* normal operation */ - BX_DEBUG(("setting slave pic IMR to %02x", value)); - BX_PIC_THIS s.slave_pic.imr = value; - service_slave_pic(); - return; - break; - } /* switch (address) */ - - return; -} - -// new IRQ signal handling routines - - void -bx_pic_c::lower_irq(unsigned irq_no) -{ -#if BX_SUPPORT_APIC - // forward this function call to the ioapic too - if (DEV_ioapic_present()) - bx_devices.ioapic->untrigger_irq (irq_no, -1); -#endif - - if ((irq_no <= 7) && (BX_PIC_THIS s.master_pic.IRQ_line[irq_no])) { - BX_DEBUG(("IRQ line %d now low", (unsigned) irq_no)); - BX_PIC_THIS s.master_pic.IRQ_line[irq_no] = 0; - BX_PIC_THIS s.master_pic.irr &= ~(1 << irq_no); - if ((BX_PIC_THIS s.master_pic.irr & ~BX_PIC_THIS s.master_pic.imr) == 0) { - BX_SET_INTR(0); - BX_PIC_THIS s.master_pic.INT = 0; - } - } else if ((irq_no > 7) && (irq_no <= 15) && - (BX_PIC_THIS s.slave_pic.IRQ_line[irq_no-8])) { - BX_DEBUG(("IRQ line %d now low", (unsigned) irq_no)); - BX_PIC_THIS s.slave_pic.IRQ_line[irq_no - 8] = 0; - BX_PIC_THIS s.slave_pic.irr &= ~(1 << (irq_no - 8)); - if ((BX_PIC_THIS s.slave_pic.irr & ~BX_PIC_THIS s.slave_pic.imr) == 0) { - BX_PIC_THIS s.slave_pic.INT = 0; - lower_irq(2); - } - } -} - - void -bx_pic_c::raise_irq(unsigned irq_no) -{ -#if BX_SUPPORT_APIC - // forward this function call to the ioapic too - bx_devices.ioapic->trigger_irq (irq_no, -1); -#endif - - if ((irq_no <= 7) && (!BX_PIC_THIS s.master_pic.IRQ_line[irq_no])) { - BX_DEBUG(("IRQ line %d now high", (unsigned) irq_no)); - BX_PIC_THIS s.master_pic.IRQ_line[irq_no] = 1; - BX_PIC_THIS s.master_pic.irr |= (1 << irq_no); - service_master_pic(); - } else if ((irq_no > 7) && (irq_no <= 15) && - (!BX_PIC_THIS s.slave_pic.IRQ_line[irq_no-8])) { - BX_DEBUG(("IRQ line %d now high", (unsigned) irq_no)); - BX_PIC_THIS s.slave_pic.IRQ_line[irq_no - 8] = 1; - BX_PIC_THIS s.slave_pic.irr |= (1 << (irq_no - 8)); - service_slave_pic(); - } -} - -void bx_pic_c::clear_highest_interrupt(bx_pic_t *pic) -{ - int irq; - int lowest_priority; - int highest_priority; - - /* clear highest current in service bit */ - lowest_priority = pic->lowest_priority; - highest_priority = lowest_priority + 1; - if(highest_priority > 7) - highest_priority = 0; - - irq = highest_priority; - do { - if (pic->isr & (1 << irq)) { - pic->isr &= ~(1 << irq); - break; /* Return mask of bit cleared. */ - } - - irq ++; - if(irq > 7) - irq = 0; - } while(irq != highest_priority); - -} - - /* */ - void -bx_pic_c::service_master_pic(void) -{ - Bit8u unmasked_requests; - int irq; - Bit8u isr, max_irq; - Bit8u highest_priority = BX_PIC_THIS s.master_pic.lowest_priority + 1; - if(highest_priority > 7) - highest_priority = 0; - - if (BX_PIC_THIS s.master_pic.INT) { /* last interrupt still not acknowleged */ - return; - } - - if (BX_PIC_THIS s.master_pic.special_mask) { - /* all priorities may be enabled. check all IRR bits except ones - * which have corresponding ISR bits set - */ - max_irq = highest_priority; - } - else { /* normal mode */ - /* Find the highest priority IRQ that is enabled due to current ISR */ - isr = BX_PIC_THIS s.master_pic.isr; - if (isr) { - max_irq = highest_priority; - while ( (isr & (1 << max_irq)) == 0) { - max_irq++; - if(max_irq > 7) - max_irq = 0; - } - if (max_irq == highest_priority ) return; /* Highest priority interrupt in-service, - * no other priorities allowed */ - if (max_irq > 7) BX_PANIC(("error in service_master_pic()")); - } - else - max_irq = highest_priority; /* 0..7 bits in ISR are cleared */ - } - - - /* now, see if there are any higher priority requests */ - if ((unmasked_requests = (BX_PIC_THIS s.master_pic.irr & ~BX_PIC_THIS s.master_pic.imr)) ) { - irq = highest_priority; - do { - /* for special mode, since we're looking at all IRQ's, skip if - * current IRQ is already in-service - */ - if ( ! (BX_PIC_THIS s.master_pic.special_mask && ((BX_PIC_THIS s.master_pic.isr >> irq) & 0x01)) ) { - if (unmasked_requests & (1 << irq)) { - BX_DEBUG(("signalling IRQ(%u)", (unsigned) irq)); - BX_PIC_THIS s.master_pic.INT = 1; - BX_SET_INTR(1); - BX_PIC_THIS s.master_pic.irq = irq; - return; - } /* if (unmasked_requests & ... */ - } - - irq ++; - if(irq > 7) - irq = 0; - } while(irq != max_irq); /* do ... */ - } /* if (unmasked_requests = ... */ -} - - - void -bx_pic_c::service_slave_pic(void) -{ - Bit8u unmasked_requests; - int irq; - Bit8u isr, max_irq; - Bit8u highest_priority = BX_PIC_THIS s.slave_pic.lowest_priority + 1; - if(highest_priority > 7) - highest_priority = 0; - - if (BX_PIC_THIS s.slave_pic.INT) { /* last interrupt still not acknowleged */ - return; - } - - if (BX_PIC_THIS s.slave_pic.special_mask) { - /* all priorities may be enabled. check all IRR bits except ones - * which have corresponding ISR bits set - */ - max_irq = highest_priority; - } - else { /* normal mode */ - /* Find the highest priority IRQ that is enabled due to current ISR */ - isr = BX_PIC_THIS s.slave_pic.isr; - if (isr) { - max_irq = highest_priority; - while ( (isr & (1 << max_irq)) == 0) { - max_irq++; - if(max_irq > 7) - max_irq = 0; - } - if (max_irq == highest_priority ) return; /* Highest priority interrupt in-service, - * no other priorities allowed */ - if (max_irq > 7) BX_PANIC(("error in service_master_pic()")); - } - else - max_irq = highest_priority; /* 0..7 bits in ISR are cleared */ - } - - - /* now, see if there are any higher priority requests */ - if ((unmasked_requests = (BX_PIC_THIS s.slave_pic.irr & ~BX_PIC_THIS s.slave_pic.imr)) ) { - irq = highest_priority; - do { - /* for special mode, since we're looking at all IRQ's, skip if - * current IRQ is already in-service - */ - if ( ! (BX_PIC_THIS s.slave_pic.special_mask && ((BX_PIC_THIS s.slave_pic.isr >> irq) & 0x01)) ) { - if (unmasked_requests & (1 << irq)) { - BX_DEBUG(("slave: signalling IRQ(%u)", (unsigned) 8 + irq)); - - BX_PIC_THIS s.slave_pic.INT = 1; - BX_PIC_THIS s.slave_pic.irq = irq; - BX_PIC_THIS raise_irq(2); /* request IRQ 2 on master pic */ - return; - } /* if (unmasked_requests & ... */ - } - - irq ++; - if(irq > 7) - irq = 0; - } while(irq != max_irq); /* do ... */ - } /* if (unmasked_requests = ... */ -} - - - /* CPU handshakes with PIC after acknowledging interrupt */ - Bit8u -bx_pic_c::IAC(void) -{ - Bit8u vector; - Bit8u irq; - - BX_SET_INTR(0); - BX_PIC_THIS s.master_pic.INT = 0; - BX_PIC_THIS s.master_pic.irr &= ~(1 << BX_PIC_THIS s.master_pic.irq); - // In autoeoi mode don't set the isr bit. - if(!BX_PIC_THIS s.master_pic.auto_eoi) - BX_PIC_THIS s.master_pic.isr |= (1 << BX_PIC_THIS s.master_pic.irq); - else if(BX_PIC_THIS s.master_pic.rotate_on_autoeoi) - BX_PIC_THIS s.master_pic.lowest_priority = BX_PIC_THIS s.master_pic.irq; - - if (BX_PIC_THIS s.master_pic.irq != 2) { - irq = BX_PIC_THIS s.master_pic.irq; - vector = irq + BX_PIC_THIS s.master_pic.interrupt_offset; - } - else { /* IRQ2 = slave pic IRQ8..15 */ - BX_PIC_THIS s.slave_pic.INT = 0; - BX_PIC_THIS s.master_pic.IRQ_line[2] = 0; - irq = BX_PIC_THIS s.slave_pic.irq; - vector = irq + BX_PIC_THIS s.slave_pic.interrupt_offset; - BX_PIC_THIS s.slave_pic.irr &= ~(1 << BX_PIC_THIS s.slave_pic.irq); - // In autoeoi mode don't set the isr bit. - if(!BX_PIC_THIS s.slave_pic.auto_eoi) - BX_PIC_THIS s.slave_pic.isr |= (1 << BX_PIC_THIS s.slave_pic.irq); - else if(BX_PIC_THIS s.slave_pic.rotate_on_autoeoi) - BX_PIC_THIS s.slave_pic.lowest_priority = BX_PIC_THIS s.slave_pic.irq; - service_slave_pic(); - irq += 8; // for debug printing purposes - } - - service_master_pic(); - - BX_DBG_IAC_REPORT(vector, irq); - return(vector); -} - - Bit8u -bx_pic_c::irq_to_vec(Bit8u irq) -{ - Bit8u vector = 0; - - if (irq >= 8 && irq <= 15) - vector = irq + BX_PIC_THIS s.slave_pic.interrupt_offset; - else if (irq != 2 && irq <= 7) - vector = irq + BX_PIC_THIS s.master_pic.interrupt_offset; - else - BX_ERROR(("invalid irq!\n")); - - return vector; -} - - void -bx_pic_c::show_pic_state(void) -{ -#if defined(BX_DEBUGGER) && (BX_DEBUGGER == 1) -dbg_printf("s.master_pic.imr = %02x\n", BX_PIC_THIS s.master_pic.imr); -dbg_printf("s.master_pic.isr = %02x\n", BX_PIC_THIS s.master_pic.isr); -dbg_printf("s.master_pic.irr = %02x\n", BX_PIC_THIS s.master_pic.irr); -dbg_printf("s.master_pic.irq = %02x\n", BX_PIC_THIS s.master_pic.irq); -dbg_printf("s.slave_pic.imr = %02x\n", BX_PIC_THIS s.slave_pic.imr); -dbg_printf("s.slave_pic.isr = %02x\n", BX_PIC_THIS s.slave_pic.isr); -dbg_printf("s.slave_pic.irr = %02x\n", BX_PIC_THIS s.slave_pic.irr); -dbg_printf("s.slave_pic.irq = %02x\n", BX_PIC_THIS s.slave_pic.irq); -#endif -} diff --git a/tools/ioemu/iodev/pic.h b/tools/ioemu/iodev/pic.h deleted file mode 100644 index 378809d67d..0000000000 --- a/tools/ioemu/iodev/pic.h +++ /dev/null @@ -1,97 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pic.h,v 1.11 2003/08/04 16:03:09 akrisak Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -#if BX_USE_PIC_SMF -# define BX_PIC_SMF static -# define BX_PIC_THIS thePic-> -#else -# define BX_PIC_SMF -# define BX_PIC_THIS this-> -#endif - - - -typedef struct { - Bit8u single_PIC; /* 0=cascaded PIC, 1=master only */ - Bit8u interrupt_offset; /* programmable interrupt vector offset */ - union { - Bit8u slave_connect_mask; /* for master, a bit for each interrupt line - 0=not connect to a slave, 1=connected */ - Bit8u slave_id; /* for slave, id number of slave PIC */ - } u; - Bit8u sfnm; /* specially fully nested mode: 0=no, 1=yes*/ - Bit8u buffered_mode; /* 0=no buffered mode, 1=buffered mode */ - Bit8u master_slave; /* master/slave: 0=slave PIC, 1=master PIC */ - Bit8u auto_eoi; /* 0=manual EOI, 1=automatic EOI */ - Bit8u imr; /* interrupt mask register, 1=masked */ - Bit8u isr; /* in service register */ - Bit8u irr; /* interrupt request register */ - Bit8u read_reg_select; /* 0=IRR, 1=ISR */ - Bit8u irq; /* current IRQ number */ - Bit8u lowest_priority; /* current lowest priority irq */ - bx_bool INT; /* INT request pin of PIC */ - bx_bool IRQ_line[8]; /* IRQ pins of PIC */ - struct { - bx_bool in_init; - bx_bool requires_4; - int byte_expected; - } init; - bx_bool special_mask; - bx_bool polled; /* Set when poll command is issued. */ - bx_bool rotate_on_autoeoi; /* Set when should rotate in auto-eoi mode. */ - } bx_pic_t; - - -class bx_pic_c : public bx_pic_stub_c { -public: - bx_pic_c(void); - ~bx_pic_c(void); - virtual void init(void); - virtual void reset(unsigned type); - virtual void lower_irq(unsigned irq_no); - virtual void raise_irq(unsigned irq_no); - virtual Bit8u IAC(void); - virtual void show_pic_state(void); - Bit8u irq_to_vec(Bit8u); - -private: - struct { - bx_pic_t master_pic; - bx_pic_t slave_pic; - } s; - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); -#if !BX_USE_PIC_SMF - Bit32u read(Bit32u address, unsigned io_len); - void write(Bit32u address, Bit32u value, unsigned io_len); -#endif - - BX_PIC_SMF void service_master_pic(void); - BX_PIC_SMF void service_slave_pic(void); - BX_PIC_SMF void clear_highest_interrupt(bx_pic_t *pic); - }; diff --git a/tools/ioemu/iodev/pit.cc b/tools/ioemu/iodev/pit.cc deleted file mode 100644 index cf4777a759..0000000000 --- a/tools/ioemu/iodev/pit.cc +++ /dev/null @@ -1,856 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pit.cc,v 1.15 2003/07/31 12:04:48 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - -#include "bochs.h" - -#if (BX_USE_NEW_PIT==0) - -#define LOG_THIS bx_pit. - - -// NOTES ON THE 8253/8254 PIT MODES - -// MODE 0: Interrupt on Terminal Count -// =================================== -// Writing new count action: -// loaded upon next CLK pulse. counting doesn't start until GATE=1 -// GATE 0..1 transition: -// ??? -// GATE 1..0 transition: -// counter expiration action: -// wraps to FFFF -// * OUT rises until new count val or new control word for mode 0 written - -// MODE 1: Programmable Monoflop -// ============================= -// Writing new count action: -// not effective for current process -// GATE 0..1 transition: -// loads counter -// counter expiration action: -// wraps to FFFF -// NOTES: -// OUT rises until new count val or new control word for mode 0 written - -// MODE 2: Rate Generator -// ====================== -// Writing new count action: -// ??? -// GATE 0..1 transition: -// loads initial count val and starts counting -// counter expiration action: -// reloads after count expires -// NOTES: -// * after control word & initial count val N loaded, PIT starts -// counting upon next CLK pulse. -// * when counter reaches 1, OUT drops to a low level, for one -// CLK cycle. (short peak pulse generated) -// * afterwards, the initial count val is automatically reloaded -// and the PIT restarts the same counting operation again. -// * distance of two OUT pulses is N CLK cycles long. -// * GATE=1 enables, GATE=0 disables counter. -// * if GATE drops to low level during counting operation and rises -// to high level later, PIT loads initial count value at the -// rise and starts counting. -// * PIT starts counting after last data byte written if GATE=1 -// * if the output is low when the gate goes low, the output is -// immediately set high. - -// MODE 3: Square Wave Generator -// ============================= -// Writing new count action: -// ??? -// GATE 0..1 transition: -// ??? -// counter expiration action: -// reloads after count expires -// NOTES: -// * initially OUT at a high level -// * drop of GATE to a low level while OUT low, raises OUT to a high level -// * a rise from a low to a high level at GATE (trigger pulse), -// loads the counter with the initial count value and starts -// counting operation -// * a new count value supplied during the course of an active -// counting operation doesn't affect the current process. -// At the end of the current half cycle, the PIT loads the new value -// * if the GATE line goes low, count is temporarily halted until GATE -// returns high -// * if the OUT line is high when GATE goes low, OUT is forced low. -// ??? different for odd/even counts - -// MODE 4: Software Triggered Pulse -// ================================ -// Writing new count action: -// ??? -// GATE 0..1 transition: -// ??? -// counter expiration action: -// wraps to FFFF -// NOTES: - -// MODE 5: Hardware Triggered Pulse -// ================================ -// Writing new count action: -// ??? -// GATE 0..1 transition: -// ??? -// counter expiration action: -// wraps to FFFF -// NOTES: - - - -#define BX_PIT_LATCH_MODE_LSB 10 -#define BX_PIT_LATCH_MODE_MSB 11 -#define BX_PIT_LATCH_MODE_16BIT 12 - - -bx_pit_c bx_pit; -#if BX_USE_PIT_SMF -#define this (&bx_pit) -#endif - -#ifdef OUT -# undef OUT -#endif - - -bx_pit_c::bx_pit_c( void ) -{ - put("PIT"); - settype(PITLOG); - memset(&s, 0, sizeof(s)); - - /* 8254 PIT (Programmable Interval Timer) */ - - BX_PIT_THIS s.timer_handle[1] = BX_NULL_TIMER_HANDLE; - BX_PIT_THIS s.timer_handle[2] = BX_NULL_TIMER_HANDLE; -} - -bx_pit_c::~bx_pit_c( void ) -{ -} - - - int -bx_pit_c::init( void ) -{ - DEV_register_irq(0, "8254 PIT"); - DEV_register_ioread_handler(this, read_handler, 0x0040, "8254 PIT", 1); - DEV_register_ioread_handler(this, read_handler, 0x0041, "8254 PIT", 1); - DEV_register_ioread_handler(this, read_handler, 0x0042, "8254 PIT", 1); - DEV_register_ioread_handler(this, read_handler, 0x0043, "8254 PIT", 1); - DEV_register_ioread_handler(this, read_handler, 0x0061, "8254 PIT", 1); - - DEV_register_iowrite_handler(this, write_handler, 0x0040, "8254 PIT", 1); - DEV_register_iowrite_handler(this, write_handler, 0x0041, "8254 PIT", 1); - DEV_register_iowrite_handler(this, write_handler, 0x0042, "8254 PIT", 1); - DEV_register_iowrite_handler(this, write_handler, 0x0043, "8254 PIT", 1); - DEV_register_iowrite_handler(this, write_handler, 0x0061, "8254 PIT", 1); - - BX_PIT_THIS s.speaker_data_on = 0; - BX_PIT_THIS s.refresh_clock_div2 = 0; - - BX_PIT_THIS s.timer[0].mode = 3; /* periodic rate generator */ - BX_PIT_THIS s.timer[0].latch_mode = BX_PIT_LATCH_MODE_16BIT; - BX_PIT_THIS s.timer[0].input_latch_value = 0; - BX_PIT_THIS s.timer[0].input_latch_toggle = 0; - BX_PIT_THIS s.timer[0].output_latch_value = 0; - BX_PIT_THIS s.timer[0].output_latch_toggle = 0; - BX_PIT_THIS s.timer[0].output_latch_full = 0; - BX_PIT_THIS s.timer[0].counter_max = 0; /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */ - BX_PIT_THIS s.timer[0].counter = 0; /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */ - BX_PIT_THIS s.timer[0].bcd_mode = 0; /* binary counting mode */ - BX_PIT_THIS s.timer[0].GATE = 1; /* GATE tied to + logic */ - BX_PIT_THIS s.timer[0].OUT = 1; - BX_PIT_THIS s.timer[0].active = 0; - - BX_PIT_THIS s.timer[1].mode = 3; /* periodic rate generator */ - BX_PIT_THIS s.timer[1].latch_mode = BX_PIT_LATCH_MODE_16BIT; - BX_PIT_THIS s.timer[1].input_latch_value = 0; - BX_PIT_THIS s.timer[1].input_latch_toggle = 0; - BX_PIT_THIS s.timer[1].output_latch_value = 0; - BX_PIT_THIS s.timer[1].output_latch_toggle = 0; - BX_PIT_THIS s.timer[1].output_latch_full = 0; - BX_PIT_THIS s.timer[1].counter_max = 0; /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */ - BX_PIT_THIS s.timer[1].counter = 0; /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */ - BX_PIT_THIS s.timer[1].bcd_mode = 0; /* binary counting mode */ - BX_PIT_THIS s.timer[1].GATE = 1; /* GATE tied to + logic */ - BX_PIT_THIS s.timer[1].OUT = 1; - BX_PIT_THIS s.timer[1].active = 0; - - BX_PIT_THIS s.timer[2].mode = 3; /* periodic rate generator */ - BX_PIT_THIS s.timer[2].latch_mode = BX_PIT_LATCH_MODE_16BIT; - BX_PIT_THIS s.timer[2].input_latch_value = 0; - BX_PIT_THIS s.timer[2].input_latch_toggle = 0; - BX_PIT_THIS s.timer[2].output_latch_value = 0; - BX_PIT_THIS s.timer[2].output_latch_toggle = 0; - BX_PIT_THIS s.timer[2].output_latch_full = 0; - BX_PIT_THIS s.timer[2].counter_max = 0; /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */ - BX_PIT_THIS s.timer[2].counter = 0; /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */ - BX_PIT_THIS s.timer[2].bcd_mode = 0; /* binary counting mode */ - BX_PIT_THIS s.timer[2].GATE = 0; /* timer2 gate controlled by port 61h bit 0 */ - BX_PIT_THIS s.timer[2].OUT = 1; - BX_PIT_THIS s.timer[2].active = 0; - - return(1); -} - -void bx_pit_c::reset(unsigned type) { -} - - // static IO port read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_pit_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_PIT_SMF - bx_pit_c *class_ptr = (bx_pit_c *) this_ptr; - - return( class_ptr->read(address, io_len) ); -} - - - Bit32u -bx_pit_c::read( Bit32u address, unsigned int io_len ) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PIT_SMF - if (bx_dbg.pit) - BX_INFO(("pit: io read from port %04x", (unsigned) address)); - - switch (address) { - case 0x40: /* timer 0 - system ticks */ - return( read_counter(0) ); - break; - - case 0x42: /* timer 2 read */ - return( read_counter(2) ); - break; - - case 0x61: - /* AT, port 61h */ - BX_PIT_THIS s.refresh_clock_div2 = !BX_PIT_THIS s.refresh_clock_div2; - return( (BX_PIT_THIS s.timer[2].OUT<<5) | - (BX_PIT_THIS s.refresh_clock_div2<<4) | - (BX_PIT_THIS s.speaker_data_on<<1) | - (BX_PIT_THIS s.timer[2].GATE) ); - break; - - default: - BX_PANIC(("pit: unsupported io read from port %04x", address)); - } - return(0); /* keep compiler happy */ -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_pit_c::write_handler(void *this_ptr, Bit32u address, Bit32u dvalue, unsigned io_len) -{ -#if !BX_USE_PIT_SMF - bx_pit_c *class_ptr = (bx_pit_c *) this_ptr; - - class_ptr->write(address, dvalue, io_len); -} - - void -bx_pit_c::write( Bit32u address, Bit32u dvalue, - unsigned int io_len ) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PIT_SMF - Bit8u command, mode, bcd_mode; - Bit8u value; - - value = (Bit8u ) dvalue; - - if (bx_dbg.pit) - BX_INFO(("pit: write to port %04x = %02x", - (unsigned) address, (unsigned) value)); - - switch (address) { - case 0x40: /* timer 0: write count register */ - write_count_reg( value, 0 ); - break; - - case 0x41: /* timer 1: write count register */ - write_count_reg( value, 1 ); - break; - - case 0x42: /* timer 2: write count register */ - write_count_reg( value, 2 ); - break; - - case 0x43: /* timer 0-2 mode control */ - /* |7 6 5 4|3 2 1|0| - * |-------|-----|-| - * |command|mode |bcd/binary| - */ - command = value >> 4; - mode = (value >> 1) & 0x07; - bcd_mode = value & 0x01; -#if 0 -BX_INFO(("timer 0-2 mode control: comm:%02x mode:%02x bcd_mode:%u", - (unsigned) command, (unsigned) mode, (unsigned) bcd_mode)); -#endif - - if ( (mode > 5) || (command > 0x0e) ) - BX_PANIC(("pit: outp(43h)=%02xh out of range", (unsigned) value)); - if (bcd_mode) - BX_PANIC(("pit: outp(43h)=%02xh: bcd mode unhandled", - (unsigned) bcd_mode)); - - switch (command) { - case 0x0: /* timer 0: counter latch */ - latch( 0 ); - break; - - case 0x1: /* timer 0: LSB mode */ - case 0x2: /* timer 0: MSB mode */ - BX_PANIC(("pit: outp(43h): command %02xh unhandled", - (unsigned) command)); - break; - case 0x3: /* timer 0: 16-bit mode */ - BX_PIT_THIS s.timer[0].mode = mode; - BX_PIT_THIS s.timer[0].latch_mode = BX_PIT_LATCH_MODE_16BIT; - BX_PIT_THIS s.timer[0].input_latch_value = 0; - BX_PIT_THIS s.timer[0].input_latch_toggle = 0; - BX_PIT_THIS s.timer[0].bcd_mode = bcd_mode; - if ( (mode!=3 && mode!=2 && mode!=0) || bcd_mode!=0 ) - BX_PANIC(("pit: outp(43h): comm 3, mode %02x, bcd %02x unhandled", - (unsigned) mode, bcd_mode)); - break; - case 0x4: /* timer 1: counter latch */ - latch( 1 ); - break; - - case 0x5: /* timer 1: LSB mode */ - case 0x6: /* timer 1: MSB mode */ - BX_INFO(("pit: outp(43h): command %02xh unhandled (ignored)", - (unsigned) command)); - break; - case 0x7: /* timer 1: 16-bit mode */ - BX_PIT_THIS s.timer[1].mode = mode; - BX_PIT_THIS s.timer[1].latch_mode = BX_PIT_LATCH_MODE_16BIT; - BX_PIT_THIS s.timer[1].input_latch_value = 0; - BX_PIT_THIS s.timer[1].input_latch_toggle = 0; - BX_PIT_THIS s.timer[1].bcd_mode = bcd_mode; - if ( (mode!=3 && mode!=2 && mode!=0) || bcd_mode!=0 ) - BX_PANIC(("pit: outp(43h): comm 7, mode %02x, bcd %02x unhandled", - (unsigned) mode, bcd_mode)); - break; - case 0x8: /* timer 2: counter latch */ - latch( 2 ); - break; - - case 0x9: /* timer 2: LSB mode */ - case 0xa: /* timer 2: MSB mode */ - BX_PANIC(("pit: outp(43h): command %02xh unhandled", - (unsigned) command)); - break; - case 0xb: /* timer 2: 16-bit mode */ - BX_PIT_THIS s.timer[2].mode = mode; - BX_PIT_THIS s.timer[2].latch_mode = BX_PIT_LATCH_MODE_16BIT; - BX_PIT_THIS s.timer[2].input_latch_value = 0; - BX_PIT_THIS s.timer[2].input_latch_toggle = 0; - BX_PIT_THIS s.timer[2].bcd_mode = bcd_mode; - if ( (mode!=3 && mode!=2 && mode!=0) || bcd_mode!=0 ) - BX_PANIC(("pit: outp(43h): comm Bh, mode %02x, bcd %02x unhandled", - (unsigned) mode, bcd_mode)); - break; -#if 0 - case 0xd: /* general counter latch */ - if (value & 0x08) /* select counter 2 */ - latch( 2 ); - if (value & 0x04) /* select counter 1 */ - latch( 1 ); - if (value & 0x02) /* select counter 0 */ - latch( 0 ); - break; - - case 0xe: /* latch status of timers */ - BX_PANIC(("pit: outp(43h): command %02xh unhandled", - (unsigned) command); - break; -#endif - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - BX_INFO(("pit: ignoring 8254 command %u", (unsigned) command)); - break; - - default: /* 0xc & 0xf */ - BX_PANIC(("pit: outp(43h) command %1xh unhandled", - (unsigned) command)); - break; - } - break; - - case 0x61: - BX_PIT_THIS s.speaker_data_on = (value >> 1) & 0x01; -/*??? only on AT+ */ - set_GATE(2, value & 0x01); -#if BX_CPU_LEVEL < 2 - /* ??? XT: */ - bx_kbd_port61h_write(value); -#endif - break; - - default: - BX_PANIC(("pit: unsupported io write to port %04x = %02x", - (unsigned) address, (unsigned) value)); - } -} - - - - - void -bx_pit_c::write_count_reg( Bit8u value, unsigned timerid ) -{ - bx_bool xfer_complete; - - switch ( BX_PIT_THIS s.timer[timerid].latch_mode ) { - case BX_PIT_LATCH_MODE_16BIT: /* write1=LSB, write2=MSB */ - if (BX_PIT_THIS s.timer[timerid].input_latch_toggle==0) { - BX_PIT_THIS s.timer[timerid].input_latch_value = value; - BX_PIT_THIS s.timer[timerid].input_latch_toggle = 1; - xfer_complete = 0; - if (bx_dbg.pit) - BX_INFO(("pit: BX_PIT_THIS s.timer[timerid] write L = %02x", (unsigned) value)); - } - else { - BX_PIT_THIS s.timer[timerid].input_latch_value |= (value << 8); - BX_PIT_THIS s.timer[timerid].input_latch_toggle = 0; - xfer_complete = 1; - if (bx_dbg.pit) - BX_INFO(("pit: BX_PIT_THIS s.timer[timerid] write H = %02x", (unsigned) value)); - } - break; - - case BX_PIT_LATCH_MODE_MSB: /* write1=MSB, LSB=0 */ - BX_PIT_THIS s.timer[timerid].input_latch_value = (value << 8); - xfer_complete = 1; - if (bx_dbg.pit) - BX_INFO(("pit: BX_PIT_THIS s.timer[timerid] write H = %02x", (unsigned) value)); - break; - - case BX_PIT_LATCH_MODE_LSB: /* write1=LSB, MSB=0 */ - BX_PIT_THIS s.timer[timerid].input_latch_value = value; - xfer_complete = 1; - if (bx_dbg.pit) - BX_INFO(("pit: BX_PIT_THIS s.timer[timerid] write L = %02x", (unsigned) value)); - break; - - default: - BX_PANIC(("write_count_reg: latch_mode unknown")); - xfer_complete = 0; - } - - if (xfer_complete) { - BX_PIT_THIS s.timer[timerid].counter_max = BX_PIT_THIS s.timer[timerid].input_latch_value; - - // reprogramming counter clears latch - BX_PIT_THIS s.timer[timerid].output_latch_full = 0; - - // counter bounds - // mode minimum maximum - // 0 1 0 - // 1 1 0 - // 2 2 0 - // 3 2 0 - // 4 1 0 - // 5 1 0 - switch (BX_PIT_THIS s.timer[timerid].mode) { - case 0: - BX_PIT_THIS s.timer[timerid].counter = BX_PIT_THIS s.timer[timerid].counter_max; - BX_PIT_THIS s.timer[timerid].active = 1; - if (BX_PIT_THIS s.timer[timerid].GATE) { - BX_PIT_THIS s.timer[timerid].OUT = 0; // OUT pin starts low - start( timerid ); - } - break; - case 1: - BX_PANIC(("pit:write_count_reg(%u): mode1 unsupported", - timerid)); - break; - case 2: - if ( BX_PIT_THIS s.timer[timerid].counter_max == 1 ) - BX_PANIC(("pit:write_count_reg(%u): mode %u counter_max=1", - timerid, (unsigned) BX_PIT_THIS s.timer[timerid].mode)); - if ( BX_PIT_THIS s.timer[timerid].GATE && !BX_PIT_THIS s.timer[timerid].active ) { - // software triggered - BX_PIT_THIS s.timer[timerid].counter = BX_PIT_THIS s.timer[timerid].counter_max; - BX_PIT_THIS s.timer[timerid].active = 1; - BX_PIT_THIS s.timer[timerid].OUT = 1; // initially set high - start( timerid ); - } - break; - case 3: - if ( BX_PIT_THIS s.timer[timerid].counter_max == 1 ) - BX_PANIC(("pit:write_count_reg(%u): mode %u counter_max=1", - timerid, (unsigned) BX_PIT_THIS s.timer[timerid].mode)); - BX_PIT_THIS s.timer[timerid].counter_max = BX_PIT_THIS s.timer[timerid].counter_max & 0xfffe; - if ( BX_PIT_THIS s.timer[timerid].GATE && !BX_PIT_THIS s.timer[timerid].active ) { - // software triggered - BX_PIT_THIS s.timer[timerid].counter = BX_PIT_THIS s.timer[timerid].counter_max; - BX_PIT_THIS s.timer[timerid].active = 1; - BX_PIT_THIS s.timer[timerid].OUT = 1; // initially set high - start( timerid ); - } - break; - case 4: - BX_PANIC(("pit:write_count_reg(%u): mode4 unsupported", - timerid)); - break; - case 5: - BX_PANIC(("pit:write_count_reg(%u): mode5 unsupported", - timerid)); - break; - } - } -} - - - Bit8u -bx_pit_c::read_counter( unsigned timerid ) -{ - Bit16u counter_value; - Bit8u retval; - - if (BX_PIT_THIS s.timer[timerid].output_latch_full) { /* latched read */ - counter_value = BX_PIT_THIS s.timer[timerid].output_latch_value; - } - else { /* direct unlatched read */ - counter_value = BX_PIT_THIS s.timer[timerid].counter; -BX_INFO(("CV=%04x", (unsigned) BX_PIT_THIS s.timer[timerid].counter)); - } - - switch (BX_PIT_THIS s.timer[timerid].latch_mode) { - case BX_PIT_LATCH_MODE_LSB: - retval = (Bit8u ) counter_value; - BX_PIT_THIS s.timer[timerid].output_latch_full = 0; - break; - case BX_PIT_LATCH_MODE_MSB: - retval = (Bit8u ) ( counter_value >> 8 ); - BX_PIT_THIS s.timer[timerid].output_latch_full = 0; - break; - case BX_PIT_LATCH_MODE_16BIT: - if (BX_PIT_THIS s.timer[timerid].output_latch_toggle==0) { /* LSB 1st */ - retval = (Bit8u ) counter_value; - } - else { /* MSB 2nd */ - retval = (Bit8u ) ( counter_value >> 8 ); - } - BX_PIT_THIS s.timer[timerid].output_latch_toggle = !BX_PIT_THIS s.timer[timerid].output_latch_toggle; - if (BX_PIT_THIS s.timer[timerid].output_latch_toggle == 0) - BX_PIT_THIS s.timer[timerid].output_latch_full = 0; - break; - default: - BX_PANIC(("pit: io read from port 40h: unknown latch mode")); - retval = 0; /* keep compiler happy */ - } - return( retval ); -} - - - void -bx_pit_c::latch( unsigned timerid ) -{ - /* subsequent counter latch commands are ignored until value read out */ - if (BX_PIT_THIS s.timer[timerid].output_latch_full) { - BX_INFO(("pit: pit(%u) latch: output latch full, ignoring", - timerid)); - return; - } - - BX_PIT_THIS s.timer[timerid].output_latch_value = BX_PIT_THIS s.timer[timerid].counter; - - if (bx_dbg.pit) - BX_INFO(("pit: latch_value = %u", (unsigned) BX_PIT_THIS s.timer[timerid].output_latch_value)); - BX_PIT_THIS s.timer[timerid].output_latch_toggle = 0; - BX_PIT_THIS s.timer[timerid].output_latch_full = 1; -} - - void -bx_pit_c::set_GATE(unsigned pit_id, unsigned value) -{ - // GATE's for Timer 0 & Timer 1 are tied high. - if (pit_id != 2) - BX_PANIC(("pit:set_GATE: pit_id != 2")); - - value = (value > 0); - - /* if no transition of GATE input line, then nothing to do */ - if (value == BX_PIT_THIS s.timer[2].GATE) - return; - - if (value) { /* PIT2: GATE transition from 0 to 1 */ - BX_PIT_THIS s.timer[2].GATE = 1; - switch ( BX_PIT_THIS s.timer[2].mode ) { - case 0: - BX_PIT_THIS s.timer[2].counter = BX_PIT_THIS s.timer[2].counter_max; - if (BX_PIT_THIS s.timer[2].active) { - BX_PIT_THIS s.timer[2].OUT = 0; - } - start( 2 ); - break; - case 2: - // begin counting, reload counter - BX_PIT_THIS s.timer[2].active = 1; - BX_PIT_THIS s.timer[2].OUT = 1; - BX_PIT_THIS s.timer[2].counter = BX_PIT_THIS s.timer[2].counter_max; - start( 2 ); - break; - case 3: - // begin counting, reload counter - BX_PIT_THIS s.timer[2].active = 1; - BX_PIT_THIS s.timer[2].OUT = 1; - BX_PIT_THIS s.timer[2].counter = BX_PIT_THIS s.timer[2].counter_max; - start( 2 ); - break; - case 1: - case 4: - case 5: - default: - BX_PANIC(("bx_pit_c::set_GATE: unhandled timer2 mode %u", - (unsigned) BX_PIT_THIS s.timer[2].mode)); - } - } - else { // PIT2: GATE transition from 1 to 0, deactivate - BX_PIT_THIS s.timer[2].GATE = 0; - switch ( BX_PIT_THIS s.timer[2].mode ) { - case 0: - break; - case 2: - // 1) stops count, 2) OUT goes immediately high - BX_PIT_THIS s.timer[2].active = 0; - BX_PIT_THIS s.timer[2].OUT = 1; - break; - case 3: - // 1) stops count, 2) OUT goes immediately high - BX_PIT_THIS s.timer[2].active = 0; - BX_PIT_THIS s.timer[2].OUT = 1; - break; - case 1: - case 4: - case 5: - default: - BX_PANIC(("bx_pit_c::set_GATE: unhandled timer2 mode %u", - (unsigned) BX_PIT_THIS s.timer[2].mode)); - } - } -} - - - void -bx_pit_c::start(unsigned timerid) -{ - unsigned long period_hz; - - if (BX_PIT_THIS s.timer[timerid].counter_max == 0x0000) { - period_hz = 1193182 / 65536; - } - else { - period_hz = 1193182 / BX_PIT_THIS s.timer[timerid].counter_max; - } - BX_INFO(("timer%u period set to %lu hz", timerid, period_hz)); - - - switch (BX_PIT_THIS s.timer[timerid].mode) { - case 0: /* single timeout */ - break; - case 1: /* retriggerable one-shot */ - BX_PANIC(("start: mode %u unhandled", - (unsigned) BX_PIT_THIS s.timer[timerid].mode)); - break; - case 2: /* rate generator */ - break; - case 3: /* square wave mode */ - break; - case 4: /* software triggered strobe */ - BX_PANIC(("start: mode %u unhandled", - (unsigned) BX_PIT_THIS s.timer[timerid].mode)); - break; - case 5: /* hardware retriggerable strobe */ - BX_PANIC(("start: mode %u unhandled", - (unsigned) BX_PIT_THIS s.timer[timerid].mode)); - break; - default: - BX_PANIC(("start: timer%u has bad mode", - (unsigned) BX_PIT_THIS s.timer[timerid].mode)); - } -} - - - - - int -bx_pit_c::SaveState( class state_file *fd ) -{ - fd->write_check ("8254 start"); - fd->write (&BX_PIT_THIS s, sizeof (BX_PIT_THIS s)); - fd->write_check ("8254 end"); - return(0); -} - - - int -bx_pit_c::LoadState( class state_file *fd ) -{ - fd->read_check ("8254 start"); - fd->read (&BX_PIT_THIS s, sizeof (BX_PIT_THIS s)); - fd->read_check ("8254 end"); - return(0); -} - - -#if 0 - void -bx_kbd_port61h_write(Bit8u value) -{ -// PcError("KBD_PORT61H_WRITE(): not implemented yet"); - UNUSED( value ); -} -#endif - - - bx_bool -bx_pit_c::periodic( Bit32u usec_delta ) -{ - bx_bool prev_timer0_out; - - prev_timer0_out = BX_PIT_THIS s.timer[0].OUT; - - for (unsigned i = 0; i < 3; i++) { - // is timer enabled and active? - if ( BX_PIT_THIS s.timer[i].GATE && BX_PIT_THIS s.timer[i].active ) { - switch ( BX_PIT_THIS s.timer[i].mode ) { - case 0: // Mode 0: Single Timeout - // wraps after count expires - if ( BX_PIT_THIS s.timer[i].counter == 0 ) { - // counter previously expired, wrap counter - BX_PIT_THIS s.timer[i].counter = 0xffff; - } - else if ( usec_delta >= BX_PIT_THIS s.timer[i].counter ) { - // counter expired - BX_PIT_THIS s.timer[i].counter = 0; - BX_PIT_THIS s.timer[i].OUT = 1; - } - else { - // decrement counter by elapsed useconds - BX_PIT_THIS s.timer[i].counter -= (Bit16u ) usec_delta; - } - break; - - case 1: // Mode 1: Retriggerable One-Shot - // wraps after count expires - BX_PANIC(("bx_pit_c::periodic: bad mode: timer[%u], mode %u", - i, (unsigned) BX_PIT_THIS s.timer[i].mode)); - break; - - case 2: // Mode 2: Rate Generator - // reloads after count expires - // OUT is low when counter=1, high otherwise - // min count=2, max count=0 - if ( BX_PIT_THIS s.timer[i].counter == 0 ) { - // max counter val, just wrap - BX_PIT_THIS s.timer[i].counter = 0xffff; - BX_PIT_THIS s.timer[i].OUT = 1; - } - else if ( BX_PIT_THIS s.timer[i].counter == 1 ) { - // counter previously expired, reload - BX_PIT_THIS s.timer[i].counter = BX_PIT_THIS s.timer[i].counter_max; - BX_PIT_THIS s.timer[i].OUT = 1; - } - else if ( (BX_PIT_THIS s.timer[i].counter == 2) || - (usec_delta >= (Bit32u(BX_PIT_THIS s.timer[i].counter) - 1)) ) { - // in either case, counter will reach 1 - BX_PIT_THIS s.timer[i].counter = 1; - BX_PIT_THIS s.timer[i].OUT = 0; - } - else { - // decrement counter by elapsed useconds - BX_PIT_THIS s.timer[i].counter -= (Bit16u ) usec_delta; - } - break; - - case 3: // Mode 3: Square Wave Mode - // reloads after count expires - // min count=2, max count=0 - if ( BX_PIT_THIS s.timer[i].counter == 0 ) { - // max count, dec by 2 - BX_PIT_THIS s.timer[i].counter = 0xfffe; - } - else if ( (BX_PIT_THIS s.timer[i].counter <= 2) || - ( (usec_delta*2) >= BX_PIT_THIS s.timer[i].counter ) ) { - // counter expired, reload - BX_PIT_THIS s.timer[i].counter = BX_PIT_THIS s.timer[i].counter_max; - BX_PIT_THIS s.timer[i].OUT = !BX_PIT_THIS s.timer[i].OUT; - //BX_INFO(("CV: reload t%u to %04x", (unsigned) i, (unsigned) - // BX_PIT_THIS s.timer[i].counter)); - } - else { - // decrement counter by elapsed useconds - BX_PIT_THIS s.timer[i].counter -= (Bit16u ) ( 2*usec_delta ); - //BX_INFO(("CV: dec count to %04x", - // (unsigned) BX_PIT_THIS s.timer[i].counter)); - } - break; - - case 4: // Mode 4: Software Triggered Strobe - // wraps after count expires - BX_PANIC(("bx_pit_c::periodic: bad mode: timer[%u], mode %u", - i, (unsigned) BX_PIT_THIS s.timer[i].mode)); - break; - - case 5: // Mode 5: Hardware Retriggerable Strobe - // wraps after count expires - BX_PANIC(("bx_pit_c::periodic: bad mode: timer[%u], mode %u", - i, (unsigned) BX_PIT_THIS s.timer[i].mode)); - break; - default: - BX_PANIC(("bx_pit_c::periodic: bad mode: timer[%u], mode %u", - i, (unsigned) BX_PIT_THIS s.timer[i].mode)); - break; - } // switch ( BX_PIT_THIS s.tim... - } // if ( BX_PIT_THIS s.timer[i]... - } // for (unsigned i... - - // see if there's a rising edge on timer0's output to trigger an IRQ0. - if ( (prev_timer0_out==0) && (BX_PIT_THIS s.timer[0].OUT==1) ) - return(1); // request IRQ 0 - else - return(0); -} - -#endif // #if (BX_USE_NEW_PIT==0) diff --git a/tools/ioemu/iodev/pit.h b/tools/ioemu/iodev/pit.h deleted file mode 100644 index 49b663bf9d..0000000000 --- a/tools/ioemu/iodev/pit.h +++ /dev/null @@ -1,103 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pit.h,v 1.10 2002/10/25 11:44:40 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -#ifndef _BX_PIT_H -#define _BX_PIT_H - -#include "config.h" - -#if (BX_USE_NEW_PIT==0) - -#if BX_USE_PIT_SMF -# define BX_PIT_SMF static -# define BX_PIT_THIS bx_pit. -#else -# define BX_PIT_SMF -# define BX_PIT_THIS this-> -#endif - -#ifdef OUT -# undef OUT -#endif - - -typedef struct { - Bit8u mode; - Bit8u latch_mode; - Bit16u input_latch_value; - bx_bool input_latch_toggle; - Bit16u output_latch_value; - bx_bool output_latch_toggle; - bx_bool output_latch_full; - Bit16u counter_max; - Bit16u counter; - bx_bool bcd_mode; - bx_bool active; - bx_bool GATE; // GATE input pin - bx_bool OUT; // OUT output pin - } bx_pit_t; - - - - -class bx_pit_c : public logfunctions { -public: - bx_pit_c( void ); - ~bx_pit_c( void ); - BX_PIT_SMF int init(void); - BX_PIT_SMF void reset( unsigned type); - BX_PIT_SMF bx_bool periodic( Bit32u usec_delta ); - - BX_PIT_SMF int SaveState( class state_file *fd ); - BX_PIT_SMF int LoadState( class state_file *fd ); - -private: - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); -#if !BX_USE_PIT_SMF - Bit32u read( Bit32u addr, unsigned int len ); - void write( Bit32u addr, Bit32u Value, unsigned int len ); -#endif - - struct s_type { - bx_pit_t timer[3]; - Bit8u speaker_data_on; - bx_bool refresh_clock_div2; - int timer_handle[3]; - } s; - - BX_PIT_SMF void write_count_reg( Bit8u value, unsigned timerid ); - BX_PIT_SMF Bit8u read_counter( unsigned timerid ); - BX_PIT_SMF void latch( unsigned timerid ); - BX_PIT_SMF void set_GATE(unsigned pit_id, unsigned value); - BX_PIT_SMF void start(unsigned timerid); - }; - -extern bx_pit_c bx_pit; - -#endif // #if (BX_USE_NEW_PIT==0) -#endif // #ifndef _BX_PIT_H diff --git a/tools/ioemu/iodev/pit82c54.cc b/tools/ioemu/iodev/pit82c54.cc deleted file mode 100644 index 493faf6ee1..0000000000 --- a/tools/ioemu/iodev/pit82c54.cc +++ /dev/null @@ -1,930 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pit82c54.cc,v 1.23 2003/06/29 17:24:52 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -/* - * Emulator of an Intel 8254/82C54 Programmable Interval Timer. - * Greg Alexander - * - * - * Things I am unclear on (greg): - * 1.)What happens if both the status and count registers are latched, - * but the first of the two count registers has already been read? - * I.E.: - * latch count 0 (16-bit) - * Read count 0 (read LSByte) - * READ_BACK status of count 0 - * Read count 0 - do you get MSByte or status? - * This will be flagged as an error. - * 2.)What happens when we latch the output in the middle of a 2-part - * unlatched read? - * 3.)I assumed that programming a counter removes a latched status. - * 4.)I implemented the 8254 description of mode 0, not the 82C54 one. - * 5.)clock() calls represent a rising clock edge followed by a falling - * clock edge. - * 6.)What happens when we trigger mode 1 in the middle of a 2-part - * write? - */ - -#include "bochs.h" -#include "pit82c54.h" -#define LOG_THIS this-> - - -void pit_82C54::print_counter(counter_type & thisctr) { -#if 1 - BX_INFO(("Printing Counter")); - BX_INFO(("count: %d",thisctr.count)); - BX_INFO(("count_binary: %x",thisctr.count_binary)); - BX_INFO(("counter gate: %x",thisctr.GATE)); - BX_INFO(("counter OUT: %x",thisctr.OUTpin)); - BX_INFO(("next_change_time: %d",thisctr.next_change_time)); - BX_INFO(("End Counter Printout")); -#endif -} - -void pit_82C54::print_cnum(Bit8u cnum) { - if(cnum>MAX_COUNTER) { - BX_ERROR(("Bad counter index to print_cnum")); - } else { - print_counter(counter[cnum]); - } -} - - void pit_82C54::latch_counter(counter_type & thisctr) { - if(thisctr.count_LSB_latched || thisctr.count_MSB_latched) { - //Do nothing because previous latch has not been read.; - } else { - switch(thisctr.read_state) { - case MSByte: - thisctr.outlatch=thisctr.count & 0xFFFF; - thisctr.count_MSB_latched=1; - break; - case LSByte: - thisctr.outlatch=thisctr.count & 0xFFFF; - thisctr.count_LSB_latched=1; - break; - case LSByte_multiple: - thisctr.outlatch=thisctr.count & 0xFFFF; - thisctr.count_LSB_latched=1; - thisctr.count_MSB_latched=1; - break; - case MSByte_multiple: - if(!(seen_problems & UNL_2P_READ)) { -// seen_problems|=UNL_2P_READ; - BX_ERROR(("Unknown behavior when latching during 2-part read.")); - BX_ERROR((" This message will not be repeated.")); - } - //I guess latching and resetting to LSB first makes sense; - BX_DEBUG(("Setting read_state to LSB_mult")); - thisctr.read_state=LSByte_multiple; - thisctr.outlatch=thisctr.count & 0xFFFF; - thisctr.count_LSB_latched=1; - thisctr.count_MSB_latched=1; - break; - default: - BX_ERROR(("Unknown read mode found during latch command.")); - break; - } - } - } - - void pit_82C54::set_OUT (counter_type & thisctr, bool data) { - //This will probably have a callback, so I put it here. - thisctr.OUTpin=data; - } - - void BX_CPP_AttrRegparmN(2) -pit_82C54::set_count (counter_type & thisctr, Bit32u data) { - thisctr.count=data & 0xFFFF; - set_binary_to_count(thisctr); - } - - void BX_CPP_AttrRegparmN(1) -pit_82C54::set_count_to_binary(counter_type & thisctr) { - if(thisctr.bcd_mode) { - thisctr.count= - (((thisctr.count_binary/1)%10)<<0) | - (((thisctr.count_binary/10)%10)<<4) | - (((thisctr.count_binary/100)%10)<<8) | - (((thisctr.count_binary/1000)%10)<<12) - ; - } else { - thisctr.count=thisctr.count_binary; - } - } - - void BX_CPP_AttrRegparmN(1) -pit_82C54::set_binary_to_count(counter_type & thisctr) { - if(thisctr.bcd_mode) { - thisctr.count_binary= - (1*((thisctr.count>>0)&0xF)) + - (10*((thisctr.count>>4)&0xF)) + - (100*((thisctr.count>>8)&0xF)) + - (1000*((thisctr.count>>12)&0xF)) - ; - } else { - thisctr.count_binary=thisctr.count; - } - } - - void BX_CPP_AttrRegparmN(1) -pit_82C54::decrement (counter_type & thisctr) { - if(!thisctr.count) { - if(thisctr.bcd_mode) { - thisctr.count=0x9999; - thisctr.count_binary=9999; - } else { - thisctr.count=0xFFFF; - thisctr.count_binary=0xFFFF; - } - } else { - thisctr.count_binary--; - set_count_to_binary(thisctr); - } - } - - void pit_82C54::init (void) { - Bit8u i; - - put("PIT81"); - settype(PIT81LOG); - - for(i=0;i<3;i++) { - BX_DEBUG(("Setting read_state to LSB")); - counter[i].read_state=LSByte; - counter[i].write_state=LSByte; - counter[i].GATE=1; - counter[i].OUTpin=1; - counter[i].triggerGATE=0; - counter[i].mode=4; - counter[i].first_pass=0; - counter[i].bcd_mode=0; - counter[i].count=0; - counter[i].count_binary=0; - counter[i].state_bit_1=0; - counter[i].state_bit_2=0; - counter[i].null_count=0; - counter[i].rw_mode=1; - counter[i].count_written=1; - counter[i].count_LSB_latched=0; - counter[i].count_MSB_latched=0; - counter[i].status_latched=0; - counter[i].next_change_time=0; - } - seen_problems=0; - } - - pit_82C54::pit_82C54 (void) { - init(); - } - - void pit_82C54::reset (unsigned type) { - } - -void BX_CPP_AttrRegparmN(2) -pit_82C54::decrement_multiple(counter_type & thisctr, Bit32u cycles) { - while(cycles>0) { - if(cycles<=thisctr.count_binary) { - thisctr.count_binary-=cycles; - cycles-=cycles; - set_count_to_binary(thisctr); - } else { - cycles-=(thisctr.count_binary+1); - thisctr.count_binary-=thisctr.count_binary; - set_count_to_binary(thisctr); - decrement(thisctr); - } - } -} - -void pit_82C54::clock_multiple(Bit8u cnum, Bit32u cycles) { - if(cnum>MAX_COUNTER) { - BX_ERROR(("Counter number too high in clock")); - } else { - counter_type & thisctr = counter[cnum]; - while(cycles>0) { - if(thisctr.next_change_time==0) { - if(thisctr.count_written) { - switch(thisctr.mode) { - case 0: - if(thisctr.GATE && (thisctr.write_state!=MSByte_multiple)) { - decrement_multiple(thisctr, cycles); - } - break; - case 1: - decrement_multiple(thisctr, cycles); - break; - case 2: - if( (!thisctr.first_pass) && thisctr.GATE ) { - decrement_multiple(thisctr, cycles); - } - break; - case 3: - if( (!thisctr.first_pass) && thisctr.GATE ) { - decrement_multiple(thisctr, 2*cycles); - } - break; - case 4: - if(thisctr.GATE) { - decrement_multiple(thisctr, cycles); - } - break; - case 5: - decrement_multiple(thisctr, cycles); - break; - default: - break; - } - } - cycles-=cycles; - } else { - switch(thisctr.mode) { - case 0: - case 1: - case 2: - case 4: - case 5: - if( thisctr.next_change_time > cycles ) { - decrement_multiple(thisctr,cycles); - thisctr.next_change_time-=cycles; - cycles-=cycles; - } else { - decrement_multiple(thisctr,(thisctr.next_change_time-1)); - cycles-=thisctr.next_change_time; - clock(cnum); - } - break; - case 3: - if( thisctr.next_change_time > cycles ) { - decrement_multiple(thisctr,cycles*2); - thisctr.next_change_time-=cycles; - cycles-=cycles; - } else { - decrement_multiple(thisctr,(thisctr.next_change_time-1)*2); - cycles-=thisctr.next_change_time; - clock(cnum); - } - break; - default: - cycles-=cycles; - break; - } - } - } -#if 0 - print_counter(thisctr); -#endif - } -} - - void BX_CPP_AttrRegparmN(1) -pit_82C54::clock(Bit8u cnum) { - if(cnum>MAX_COUNTER) { - BX_ERROR(("Counter number too high in clock")); - } else { - counter_type & thisctr = counter[cnum]; - switch(thisctr.mode) { - case 0: - if(thisctr.count_written) { - if(thisctr.null_count) { - set_count(thisctr, thisctr.inlatch); - if(thisctr.GATE) { - if(thisctr.count_binary==0) { - thisctr.next_change_time=1; - } else { - thisctr.next_change_time=thisctr.count_binary & 0xFFFF; - } - } else { - thisctr.next_change_time=0; - } - thisctr.null_count=0; - } else { - if(thisctr.GATE && (thisctr.write_state!=MSByte_multiple)) { - decrement(thisctr); - if(!thisctr.OUTpin) { - thisctr.next_change_time=thisctr.count_binary & 0xFFFF; - if(!thisctr.count) { - set_OUT(thisctr,1); - } - } else { - thisctr.next_change_time=0; - } - } else { - thisctr.next_change_time=0; //if the clock isn't moving. - } - } - } else { - thisctr.next_change_time=0; //default to 0. - } - thisctr.triggerGATE=0; - break; - case 1: - if(thisctr.count_written) { - if(thisctr.triggerGATE) { - set_count(thisctr, thisctr.inlatch); - if(thisctr.count_binary==0) { - thisctr.next_change_time=1; - } else { - thisctr.next_change_time=thisctr.count_binary & 0xFFFF; - } - thisctr.null_count=0; - set_OUT(thisctr,0); - if(thisctr.write_state==MSByte_multiple) { - BX_ERROR(("Undefined behavior when loading a half loaded count.")); - } - } else { - decrement(thisctr); - if(!thisctr.OUTpin) { - if(thisctr.count_binary==0) { - thisctr.next_change_time=1; - } else { - thisctr.next_change_time=thisctr.count_binary & 0xFFFF; - } - if(thisctr.count==0) { - set_OUT(thisctr,1); - } - } else { - thisctr.next_change_time=0; - } - } - } else { - thisctr.next_change_time=0; //default to 0. - } - thisctr.triggerGATE=0; - break; - case 2: - if(thisctr.count_written) { - if(thisctr.triggerGATE || thisctr.first_pass) { - set_count(thisctr, thisctr.inlatch); - thisctr.next_change_time=(thisctr.count_binary-1) & 0xFFFF; - thisctr.null_count=0; - if(thisctr.inlatch==1) { - BX_ERROR(("ERROR: count of 1 is invalid in pit mode 2.")); - } - if(!thisctr.OUTpin) { - set_OUT(thisctr,1); - } - if(thisctr.write_state==MSByte_multiple) { - BX_ERROR(("Undefined behavior when loading a half loaded count.")); - } - thisctr.first_pass=0; - } else { - if(thisctr.GATE) { - decrement(thisctr); - thisctr.next_change_time=(thisctr.count_binary-1) & 0xFFFF; - if(thisctr.count==1) { - thisctr.next_change_time=1; - set_OUT(thisctr,0); - thisctr.first_pass=1; - } - } else { - thisctr.next_change_time=0; - } - } - } else { - thisctr.next_change_time=0; - } - thisctr.triggerGATE=0; - break; - case 3: - if(thisctr.count_written) { - if( (thisctr.triggerGATE || thisctr.first_pass - || thisctr.state_bit_2) && thisctr.GATE ) { - set_count(thisctr, thisctr.inlatch & 0xFFFE); - thisctr.state_bit_1=thisctr.inlatch & 0x1; - if( (!thisctr.OUTpin) || (!(thisctr.state_bit_1))) { - if(((thisctr.count_binary/2)-1)==0) { - thisctr.next_change_time=1; - } else { - thisctr.next_change_time=((thisctr.count_binary/2)-1) & 0xFFFF; - } - } else { - if((thisctr.count_binary/2)==0) { - thisctr.next_change_time=1; - } else { - thisctr.next_change_time=(thisctr.count_binary/2) & 0xFFFF; - } - } - thisctr.null_count=0; - if(thisctr.inlatch==1) { - BX_ERROR(("Count of 1 is invalid in pit mode 3.")); - } - if(!thisctr.OUTpin) { - set_OUT(thisctr,1); - } else if(thisctr.OUTpin && !thisctr.first_pass) { - set_OUT(thisctr,0); - } - if(thisctr.write_state==MSByte_multiple) { - BX_ERROR(("Undefined behavior when loading a half loaded count.")); - } - thisctr.state_bit_2=0; - thisctr.first_pass=0; - } else { - if(thisctr.GATE) { - decrement(thisctr); - decrement(thisctr); - if( (!thisctr.OUTpin) || (!(thisctr.state_bit_1))) { - thisctr.next_change_time=((thisctr.count_binary/2)-1) & 0xFFFF; - } else { - thisctr.next_change_time=(thisctr.count_binary/2) & 0xFFFF; - } - if(thisctr.count==0) { - thisctr.state_bit_2=1; - thisctr.next_change_time=1; - } - if( (thisctr.count==2) && - ( (!thisctr.OUTpin) || (!(thisctr.state_bit_1))) - ) { - thisctr.state_bit_2=1; - thisctr.next_change_time=1; - } - } else { - thisctr.next_change_time=0; - } - } - } else { - thisctr.next_change_time=0; - } - thisctr.triggerGATE=0; - break; - case 4: - if(thisctr.count_written) { - if(!thisctr.OUTpin) { - set_OUT(thisctr,1); - } - if(thisctr.null_count) { - set_count(thisctr, thisctr.inlatch); - if(thisctr.GATE) { - if(thisctr.count_binary==0) { - thisctr.next_change_time=1; - } else { - thisctr.next_change_time=thisctr.count_binary & 0xFFFF; - } - } else { - thisctr.next_change_time=0; - } - thisctr.null_count=0; - if(thisctr.write_state==MSByte_multiple) { - BX_ERROR(("Undefined behavior when loading a half loaded count.")); - } - thisctr.first_pass=1; - } else { - if(thisctr.GATE) { - decrement(thisctr); - if(thisctr.first_pass) { - thisctr.next_change_time=thisctr.count_binary & 0xFFFF; - if(!thisctr.count) { - set_OUT(thisctr,0); - thisctr.next_change_time=1; - thisctr.first_pass=0; - } - } else { - thisctr.next_change_time=0; - } - } else { - thisctr.next_change_time=0; - } - } - } else { - thisctr.next_change_time=0; - } - thisctr.triggerGATE=0; - break; - case 5: - if(thisctr.count_written) { - if(!thisctr.OUTpin) { - set_OUT(thisctr,1); - } - if(thisctr.triggerGATE) { - set_count(thisctr, thisctr.inlatch); - if(thisctr.count_binary==0) { - thisctr.next_change_time=1; - } else { - thisctr.next_change_time=thisctr.count_binary & 0xFFFF; - } - thisctr.null_count=0; - if(thisctr.write_state==MSByte_multiple) { - BX_ERROR(("Undefined behavior when loading a half loaded count.")); - } - thisctr.first_pass=1; - } else { - decrement(thisctr); - if(thisctr.first_pass) { - thisctr.next_change_time=thisctr.count_binary & 0xFFFF; - if(!thisctr.count) { - set_OUT(thisctr,0); - thisctr.next_change_time=1; - thisctr.first_pass=0; - } - } else { - thisctr.next_change_time=0; - } - } - } else { - thisctr.next_change_time=0; - } - thisctr.triggerGATE=0; - break; - default: - BX_ERROR(("Mode not implemented.")); - thisctr.next_change_time=0; - thisctr.triggerGATE=0; - break; - } - } - } - - void pit_82C54::clock_all(Bit32u cycles) { - BX_DEBUG(("clock_all: cycles=%d",cycles)); - clock_multiple(0,cycles); - clock_multiple(1,cycles); - clock_multiple(2,cycles); - } - - Bit8u pit_82C54::read(Bit8u address) { - if(address>MAX_ADDRESS) { - BX_ERROR(("Counter address incorrect in data read.")); - } else if(address==CONTROL_ADDRESS) { - BX_DEBUG(("PIT Read: Control Word Register.")); - //Read from control word register; - /* This might be okay. If so, 0 seems the most logical - * return value from looking at the docs. - */ - BX_ERROR(("Read from control word register not defined.")); - return 0; - } else { - //Read from a counter; - BX_DEBUG(("PIT Read: Counter %d.",address)); - counter_type & thisctr=counter[address]; - if(thisctr.status_latched) { - //Latched Status Read; - if(thisctr.count_MSB_latched && - (thisctr.read_state==MSByte_multiple) ) { - BX_ERROR(("Undefined output when status latched and count half read.")); - } else { - thisctr.status_latched=0; - return thisctr.status_latch; - } - } else { - //Latched Count Read; - if(thisctr.count_LSB_latched) { - //Read Least Significant Byte; - if(thisctr.read_state==LSByte_multiple) { - BX_DEBUG(("Setting read_state to MSB_mult")); - thisctr.read_state=MSByte_multiple; - } - thisctr.count_LSB_latched=0; - return (thisctr.outlatch & 0xFF); - } else if(thisctr.count_MSB_latched) { - //Read Most Significant Byte; - if(thisctr.read_state==MSByte_multiple) { - BX_DEBUG(("Setting read_state to LSB_mult")); - thisctr.read_state=LSByte_multiple; - } - thisctr.count_MSB_latched=0; - return ((thisctr.outlatch>>8) & 0xFF); - } else { - //Unlatched Count Read; - if(!(thisctr.read_state & 0x1)) { - //Read Least Significant Byte; - if(thisctr.read_state==LSByte_multiple) { - thisctr.read_state=MSByte_multiple; - BX_DEBUG(("Setting read_state to MSB_mult")); - } - return (thisctr.count & 0xFF); - } else { - //Read Most Significant Byte; - if(thisctr.read_state==MSByte_multiple) { - BX_DEBUG(("Setting read_state to LSB_mult")); - thisctr.read_state=LSByte_multiple; - } - return ((thisctr.count>>8) & 0xFF); - } - } - } - } - //Should only get here on errors; - return 0; - } - -#ifdef BX_VMX_PIT -//extra operations when use vmx pit device model - void pit_82C54::write_initcount_vmx(Bit8u cnum) { - if(cnum>MAX_COUNTER) { - BX_ERROR(("Counter number incorrect\n")); - } - - ioreq_t *req = &((vcpu_iodata_t *) shared_page)->vp_ioreq; - extern bx_pic_c *thePic; - counter_type & thisctr = counter[cnum]; - if(req->pdata_valid) { - BX_ERROR(("VMX_PIT:err!pit is port io!\n")); - } - - if (thisctr.mode == 2) {//periodic mode, need HV to help send interrupt - req->state = STATE_IORESP_HOOK; - -// req->u.data = thisctr.inlatch * 1000 / PIT_FREQ;//init count:16 bit - req->u.data = thisctr.inlatch; //init count:16 bit - //get the pit irq(0)'s vector from pic DM - req->u.data |= ((thePic->irq_to_vec(0)) << 16 ); //timer vec:8 bit - req->u.data |= (cnum << 24); //PIT channel(0~2):2 bit - req->u.data |= ((thisctr.rw_mode) << 26); //rw mode:2 bit - - BX_INFO(("VMX_PIT:whole pit hook packet = 0x%llx \n", (req->u.data ) )); - BX_INFO(("VMX_PIT:init counter = %d ms\n", (req->u.data & 0xFFFF) )); - } - - } -#endif - - void pit_82C54::write(Bit8u address, Bit8u data) { - if(address>MAX_ADDRESS) { - BX_ERROR(("Counter address incorrect in data write.")); - } else if(address==CONTROL_ADDRESS) { - Bit8u SC, RW, M, BCD; - controlword=data; - BX_DEBUG(("Control Word Write.")); - SC = (controlword>>6) & 0x3; - RW = (controlword>>4) & 0x3; - M = (controlword>>1) & 0x7; - BCD = controlword & 0x1; - if(SC == 3) { - //READ_BACK command; - int i; - BX_DEBUG(("READ_BACK command.")); - for(i=0;i<=MAX_COUNTER;i++) { - if((M>>i) & 0x1) { - //If we are using this counter; - counter_type & thisctr=counter[i]; - if(!((controlword>>5) & 1)) { - //Latch Count; - latch_counter(thisctr); - } - if(!((controlword>>4) & 1)) { - //Latch Status; - if(thisctr.status_latched) { - //Do nothing because latched status has not been read.; - } else { - thisctr.status_latch= - ((thisctr.OUTpin & 0x1) << 7) | - ((thisctr.null_count & 0x1) << 6) | - ((thisctr.rw_mode & 0x3) << 4) | - ((thisctr.mode & 0x7) << 1) | - (thisctr.bcd_mode&0x1) - ; - thisctr.status_latched=1; - } - } - } - } - } else { - counter_type & thisctr = counter[SC]; - if(!RW) { - //Counter Latch command; - BX_DEBUG(("Counter Latch command. SC=%d",SC)); - latch_counter(thisctr); - } else { - //Counter Program Command; - BX_DEBUG(("Counter Program command. SC=%d, RW=%d, M=%d, BCD=%d",SC,RW,M,BCD)); - thisctr.null_count=1; - thisctr.count_LSB_latched=0; - thisctr.count_MSB_latched=0; - thisctr.status_latched=0; - thisctr.inlatch=0; - thisctr.count_written=0; - thisctr.first_pass=1; - thisctr.rw_mode=RW; - thisctr.bcd_mode=(BCD > 0); - thisctr.mode=M; - switch(RW) { - case 0x1: - BX_DEBUG(("Setting read_state to LSB")); - thisctr.read_state=LSByte; - thisctr.write_state=LSByte; - break; - case 0x2: - BX_DEBUG(("Setting read_state to MSB")); - thisctr.read_state=MSByte; - thisctr.write_state=MSByte; - break; - case 0x3: - BX_DEBUG(("Setting read_state to LSB_mult")); - thisctr.read_state=LSByte_multiple; - thisctr.write_state=LSByte_multiple; - break; - default: - BX_ERROR(("RW field invalid in control word write.")); - break; - } - //All modes except mode 0 have initial output of 1.; - if(M) { - set_OUT(thisctr, 1); - } else { - set_OUT(thisctr, 0); - } - thisctr.next_change_time=0; - } - } - } else { - //Write to counter initial value. - counter_type & thisctr = counter[address]; - BX_DEBUG(("Write Initial Count: counter=%d, count=%d",address,data)); - switch(thisctr.write_state) { - case LSByte_multiple: - thisctr.inlatch=(thisctr.inlatch & (0xFF<<8)) | data; - thisctr.write_state=MSByte_multiple; - break; - case LSByte: - thisctr.inlatch=(thisctr.inlatch & (0xFF<<8)) | data; - thisctr.null_count=1; - thisctr.count_written=1; -#ifdef BX_VMX_PIT - write_initcount_vmx(address); -#endif - break; - case MSByte_multiple: - thisctr.write_state=LSByte_multiple; - case MSByte: //shared between MSB_multiple and MSByte - thisctr.inlatch=(thisctr.inlatch & 0xFF) | (data<<8); - thisctr.null_count=1; - thisctr.count_written=1; -#ifdef BX_VMX_PIT - write_initcount_vmx(address); -#endif - break; - default: - BX_ERROR(("write counter in invalid write state.")); - break; - } - switch(thisctr.mode) { - case 0: - if(thisctr.write_state==MSByte_multiple) { - set_OUT(thisctr,0); - } - thisctr.next_change_time=1; - break; - case 1: - if(thisctr.triggerGATE) { //for initial writes, if already saw trigger. - thisctr.next_change_time=1; - } //Otherwise, no change. - break; - case 6: - case 2: - thisctr.next_change_time=1; //FIXME: this could be loosened. - break; - case 7: - case 3: - thisctr.next_change_time=1; //FIXME: this could be loosened. - break; - case 4: - thisctr.next_change_time=1; - break; - case 5: - if(thisctr.triggerGATE) { //for initial writes, if already saw trigger. - thisctr.next_change_time=1; - } //Otherwise, no change. - break; - } - } - } - - void pit_82C54::set_GATE(Bit8u cnum, bool data) { - if(cnum>MAX_COUNTER) { - BX_ERROR(("Counter number incorrect in 82C54 set_GATE")); - } else { - counter_type & thisctr = counter[cnum]; - if(!( (thisctr.GATE&&data) || (!(thisctr.GATE||data)) )) { - BX_INFO(("Changing GATE %d to: %d",cnum,data)); - thisctr.GATE=data; - if(thisctr.GATE) { - thisctr.triggerGATE=1; - } - switch(thisctr.mode) { - case 0: - if(data && thisctr.count_written) { - if(thisctr.null_count) { - thisctr.next_change_time=1; - } else { - if( (!thisctr.OUTpin) && - (thisctr.write_state!=MSByte_multiple) - ) { - if(thisctr.count_binary==0) { - thisctr.next_change_time=1; - } else { - thisctr.next_change_time=thisctr.count_binary & 0xFFFF; - } - } else { - thisctr.next_change_time=0; - } - } - } else { - if(thisctr.null_count) { - thisctr.next_change_time=1; - } else { - thisctr.next_change_time=0; - } - } - break; - case 1: - if(data && thisctr.count_written) { //only triggers cause a change. - thisctr.next_change_time=1; - } - break; - case 2: - if(!data) { - set_OUT(thisctr,1); - thisctr.next_change_time=0; - } else { - if(thisctr.count_written) { - thisctr.next_change_time=1; - } else { - thisctr.next_change_time=0; - } - } - break; - case 3: - if(!data) { - set_OUT(thisctr,1); - thisctr.first_pass=1; - thisctr.next_change_time=0; - } else { - if(thisctr.count_written) { - thisctr.next_change_time=1; - } else { - thisctr.next_change_time=0; - } - } - break; - case 4: - if(!thisctr.OUTpin || thisctr.null_count) { - thisctr.next_change_time=1; - } else { - if(data && thisctr.count_written) { - if(thisctr.first_pass) { - if(thisctr.count_binary==0) { - thisctr.next_change_time=1; - } else { - thisctr.next_change_time=thisctr.count_binary & 0xFFFF; - } - } else { - thisctr.next_change_time=0; - } - } else { - thisctr.next_change_time=0; - } - } - break; - case 5: - if(data && thisctr.count_written) { //only triggers cause a change. - thisctr.next_change_time=1; - } - break; - default: - break; - } - } - } - } - - bool pit_82C54::read_OUT(Bit8u cnum) { - if(cnum>MAX_COUNTER) { - BX_ERROR(("Counter number incorrect in 82C54 read_OUT")); - return 0; - } else { - return counter[cnum].OUTpin; - } - } - - bool pit_82C54::read_GATE(Bit8u cnum) { - if(cnum>MAX_COUNTER) { - BX_ERROR(("Counter number incorrect in 82C54 read_GATE")); - return 0; - } else { - return counter[cnum].GATE; - } - } - -Bit32u pit_82C54::get_clock_event_time(Bit8u cnum) { - if(cnum>MAX_COUNTER) { - BX_ERROR(("Counter number incorrect in 82C54 read_GATE")); - return 0; - } else { - return counter[cnum].next_change_time; - } -} - -Bit32u pit_82C54::get_next_event_time(void) { - Bit32u out; - Bit32u time0=get_clock_event_time(0); - Bit32u time1=get_clock_event_time(1); - Bit32u time2=get_clock_event_time(2); - - out=time0; - if(time1 && (time1 - * - * This code is not yet linked into Bochs, but has been included so - * that you can experiment with it. (bbd) - */ - -#ifndef _PIT_82C54_H_ -#define _PIT_82C54_H_ 1 - -#include "bochs.h" - -#ifdef BX_USE_VMX -#define BX_VMX_PIT 1 -#define PIT_FREQ 1193181 -#endif - - -class pit_82C54 : public logfunctions { - -public: - //Please do not use these. They are public because they have to be - // to compile on some platforms. They are not to be used by other - // classes. - - enum rw_status { - LSByte=0, - MSByte=1, - LSByte_multiple=2, - MSByte_multiple=3 - }; - -private: - - enum { - MAX_COUNTER=2, - MAX_ADDRESS=3, - CONTROL_ADDRESS=3, - MAX_MODE=5 - }; - - enum real_RW_status { - LSB_real=1, - MSB_real=2, - BOTH_real=3 - }; - - enum problem_type { - UNL_2P_READ=1 - }; - - struct counter_type { - //Chip IOs; - bool GATE; //GATE Input value at end of cycle - bool OUTpin; //OUT output this cycle - - //Architected state; - Bit32u count; //Counter value this cycle - Bit16u outlatch; //Output latch this cycle - Bit16u inlatch; //Input latch this cycle - Bit8u status_latch; - - //Status Register data; - Bit8u rw_mode; //2-bit R/W mode from command word register. - Bit8u mode; //3-bit mode from command word register. - bool bcd_mode; //1-bit BCD vs. Binary setting. - bool null_count; //Null count bit of status register. - - //Latch status data; - bool count_LSB_latched; - bool count_MSB_latched; - bool status_latched; - - //Miscelaneous State; - Bit32u count_binary; //Value of the count in binary. - bool triggerGATE; //Whether we saw GATE rise this cycle. - rw_status write_state; //Read state this cycle - rw_status read_state; //Read state this cycle - bool count_written; //Whether a count written since programmed - bool first_pass; //Whether or not this is the first loaded count. - bool state_bit_1; //Miscelaneous state bits. - bool state_bit_2; - Bit32u next_change_time; //Next time something besides count changes. - //0 means never. - }; - - counter_type counter[3]; - - Bit8u controlword; - - int seen_problems; - - void latch_counter(counter_type & thisctr); - - void set_OUT (counter_type & thisctr, bool data); - - void set_count (counter_type & thisctr, Bit32u data) BX_CPP_AttrRegparmN(2); - - void set_count_to_binary (counter_type & thisctr) BX_CPP_AttrRegparmN(1); - - void set_binary_to_count (counter_type & thisctr) BX_CPP_AttrRegparmN(1); - - void decrement (counter_type & thisctr) BX_CPP_AttrRegparmN(1); - - void decrement_multiple(counter_type & thisctr, Bit32u cycles) BX_CPP_AttrRegparmN(2); - - void clock(Bit8u cnum) BX_CPP_AttrRegparmN(1); - - void print_counter(counter_type & thisctr); - -#ifdef BX_USE_VMX - void write_initcount_vmx(Bit8u cnum); -#endif - -public: - void init (void); - void reset (unsigned type); - pit_82C54 (void); - - void clock_all(Bit32u cycles); - void clock_multiple(Bit8u cnum, Bit32u cycles); - - Bit8u read(Bit8u address); - void write(Bit8u address, Bit8u data); - - void set_GATE(Bit8u cnum, bool data); - bool read_GATE(Bit8u cnum); - - bool read_OUT(Bit8u cnum); - - Bit32u get_clock_event_time(Bit8u cnum); - Bit32u get_next_event_time(void); - - void print_cnum(Bit8u cnum); - -}; - -#endif diff --git a/tools/ioemu/iodev/pit_wrap.cc b/tools/ioemu/iodev/pit_wrap.cc deleted file mode 100644 index 5fd1721073..0000000000 --- a/tools/ioemu/iodev/pit_wrap.cc +++ /dev/null @@ -1,444 +0,0 @@ -//////////////////////////////////////////////////////////////////////// -// $Id: pit_wrap.cc,v 1.52 2003/08/19 00:10:38 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -#include "bochs.h" - -#if BX_USE_NEW_PIT - -#include "pit_wrap.h" - - -//Important constant #defines: -#define USEC_PER_SECOND (1000000) -//1.193181MHz Clock -#define TICKS_PER_SECOND (1193181) - - -// define a macro to convert floating point numbers into 64-bit integers. -// In MSVC++ you can convert a 64-bit float into a 64-bit signed integer, -// but it will not convert a 64-bit float into a 64-bit unsigned integer. -// This macro works around that. -#define F2I(x) ((Bit64u)(Bit64s) (x)) -#define I2F(x) ((double)(Bit64s) (x)) - -//DEBUG configuration: - -//Set up Logging. -#define LOG_THIS bx_pit. - -//A single instance. -bx_pit_c bx_pit; -#if BX_USE_PIT_SMF -#define this (&bx_pit) -#endif - -//Workaround for environments where OUT is defined. -#ifdef OUT -# undef OUT -#endif - - -//Generic MAX and MIN Functions -#define BX_MAX(a,b) ( ((a)>(b))?(a):(b) ) -#define BX_MIN(a,b) ( ((a)>(b))?(b):(a) ) - - -//USEC_ALPHA is multiplier for the past. -//USEC_ALPHA_B is 1-USEC_ALPHA, or multiplier for the present. -#define USEC_ALPHA ((double)(.8)) -#define USEC_ALPHA_B ((double)(((double)1)-USEC_ALPHA)) -#define USEC_ALPHA2 ((double)(.5)) -#define USEC_ALPHA2_B ((double)(((double)1)-USEC_ALPHA2)) -#define ALPHA_LOWER(old,new) ((Bit64u)((oldhandle_timer(); -} - -void -bx_pit_c::handle_timer() { - Bit64u my_time_usec = bx_virt_timer.time_usec(); - Bit64u time_passed = my_time_usec-BX_PIT_THIS s.last_usec; - Bit32u time_passed32 = (Bit32u)time_passed; - - BX_DEBUG(("pit: entering timer handler")); - - if(time_passed32) { - periodic(time_passed32); - } - BX_PIT_THIS s.last_usec=BX_PIT_THIS s.last_usec + time_passed; - if(time_passed || - (BX_PIT_THIS s.last_next_event_time - != BX_PIT_THIS s.timer.get_next_event_time()) - ) { - BX_DEBUG(("pit: RESETting timer.")); - bx_virt_timer.deactivate_timer(BX_PIT_THIS s.timer_handle[0]); - BX_DEBUG(("deactivated timer.")); - if(BX_PIT_THIS s.timer.get_next_event_time()) { - bx_virt_timer.activate_timer(BX_PIT_THIS s.timer_handle[0], - (Bit32u)BX_MAX(1,TICKS_TO_USEC(BX_PIT_THIS s.timer.get_next_event_time())), - 0); - BX_DEBUG(("activated timer.")); - } - BX_PIT_THIS s.last_next_event_time = BX_PIT_THIS s.timer.get_next_event_time(); - } - BX_DEBUG(("s.last_usec="FMT_LL"d",BX_PIT_THIS s.last_usec)); - BX_DEBUG(("s.timer_id=%d",BX_PIT_THIS s.timer_handle[0])); - BX_DEBUG(("s.timer.get_next_event_time=%x",BX_PIT_THIS s.timer.get_next_event_time())); - BX_DEBUG(("s.last_next_event_time=%d",BX_PIT_THIS s.last_next_event_time)); -} - - - // static IO port read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_pit_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_PIT_SMF - bx_pit_c *class_ptr = (bx_pit_c *) this_ptr; - - return( class_ptr->read(address, io_len) ); -} - - - Bit32u -bx_pit_c::read( Bit32u address, unsigned int io_len ) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PIT_SMF - BX_DEBUG(("pit: entering read handler")); - - handle_timer(); - - Bit64u my_time_usec = bx_virt_timer.time_usec(); - - if (bx_dbg.pit) - BX_INFO(("pit: io read from port %04x", (unsigned) address)); - - switch (address) { - - case 0x40: /* timer 0 - system ticks */ - return(BX_PIT_THIS s.timer.read(0)); - break; - case 0x41: /* timer 1 read */ - return(BX_PIT_THIS s.timer.read(1)); - break; - case 0x42: /* timer 2 read */ - return(BX_PIT_THIS s.timer.read(2)); - break; - case 0x43: /* timer 1 read */ - return(BX_PIT_THIS s.timer.read(3)); - break; - - case 0x61: - /* AT, port 61h */ - BX_PIT_THIS s.refresh_clock_div2 = (bx_bool)((my_time_usec / 15) & 1); - return( (BX_PIT_THIS s.timer.read_OUT(2)<<5) | - (BX_PIT_THIS s.refresh_clock_div2<<4) | - (BX_PIT_THIS s.speaker_data_on<<1) | - (BX_PIT_THIS s.timer.read_GATE(2)?1:0) ); - break; - - default: - BX_PANIC(("pit: unsupported io read from port %04x", address)); - } - return(0); /* keep compiler happy */ -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_pit_c::write_handler(void *this_ptr, Bit32u address, Bit32u dvalue, unsigned io_len) -{ -#if !BX_USE_PIT_SMF - bx_pit_c *class_ptr = (bx_pit_c *) this_ptr; - - class_ptr->write(address, dvalue, io_len); -} - - void -bx_pit_c::write( Bit32u address, Bit32u dvalue, - unsigned int io_len ) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_PIT_SMF - Bit8u value; - Bit64u my_time_usec = bx_virt_timer.time_usec(); - Bit64u time_passed = my_time_usec-BX_PIT_THIS s.last_usec; - Bit32u time_passed32 = (Bit32u)time_passed; - - BX_DEBUG(("pit: entering write handler")); - - if(time_passed32) { - periodic(time_passed32); - } - BX_PIT_THIS s.last_usec=BX_PIT_THIS s.last_usec + time_passed; - - value = (Bit8u ) dvalue; - - if (bx_dbg.pit) - BX_INFO(("pit: write to port %04x = %02x", - (unsigned) address, (unsigned) value)); - - switch (address) { - case 0x40: /* timer 0: write count register */ - BX_PIT_THIS s.timer.write(0,value); - break; - - case 0x41: /* timer 1: write count register */ - BX_PIT_THIS s.timer.write( 1,value ); - break; - - case 0x42: /* timer 2: write count register */ - BX_PIT_THIS s.timer.write( 2,value ); - break; - - case 0x43: /* timer 0-2 mode control */ - BX_PIT_THIS s.timer.write( 3,value ); - break; - - case 0x61: - BX_PIT_THIS s.speaker_data_on = (value >> 1) & 0x01; -/*??? only on AT+ */ - BX_PIT_THIS s.timer.set_GATE(2, value & 0x01); -#if BX_CPU_LEVEL < 2 - /* ??? XT: */ - bx_kbd_port61h_write(value); -#endif - break; - - default: - BX_PANIC(("pit: unsupported io write to port %04x = %02x", - (unsigned) address, (unsigned) value)); - } - -#ifndef BX_VMX_PIT - if ((BX_PIT_THIS s.timer.read_OUT(0))==1) { - DEV_pic_raise_irq(0); - } else { - DEV_pic_lower_irq(0); - } -#endif - - if(time_passed || - (BX_PIT_THIS s.last_next_event_time - != BX_PIT_THIS s.timer.get_next_event_time()) - ) { - BX_DEBUG(("pit: RESETting timer.")); - bx_virt_timer.deactivate_timer(BX_PIT_THIS s.timer_handle[0]); - BX_DEBUG(("deactivated timer.")); - if(BX_PIT_THIS s.timer.get_next_event_time()) { - bx_virt_timer.activate_timer(BX_PIT_THIS s.timer_handle[0], - (Bit32u)BX_MAX(1,TICKS_TO_USEC(BX_PIT_THIS s.timer.get_next_event_time())), - 0); - BX_DEBUG(("activated timer.")); - } - BX_PIT_THIS s.last_next_event_time = BX_PIT_THIS s.timer.get_next_event_time(); - } - BX_DEBUG(("s.last_usec="FMT_LL"d",BX_PIT_THIS s.last_usec)); - BX_DEBUG(("s.timer_id=%d",BX_PIT_THIS s.timer_handle[0])); - BX_DEBUG(("s.timer.get_next_event_time=%x",BX_PIT_THIS s.timer.get_next_event_time())); - BX_DEBUG(("s.last_next_event_time=%d",BX_PIT_THIS s.last_next_event_time)); - -} - - - - - int -bx_pit_c::SaveState( class state_file *fd ) -{ - fd->write_check ("8254 start"); - fd->write (&BX_PIT_THIS s, sizeof (BX_PIT_THIS s)); - fd->write_check ("8254 end"); - return(0); -} - - - int -bx_pit_c::LoadState( class state_file *fd ) -{ - fd->read_check ("8254 start"); - fd->read (&BX_PIT_THIS s, sizeof (BX_PIT_THIS s)); - fd->read_check ("8254 end"); - return(0); -} - - -#if 0 - void -bx_kbd_port61h_write(Bit8u value) -{ -// PcError("KBD_PORT61H_WRITE(): not implemented yet"); - UNUSED( value ); -} -#endif - - - bx_bool -bx_pit_c::periodic( Bit32u usec_delta ) -{ - bx_bool prev_timer0_out = BX_PIT_THIS s.timer.read_OUT(0); - bx_bool want_interrupt = 0; - Bit32u ticks_delta = 0; - -#ifdef BX_SCHEDULED_DIE_TIME - if (bx_pc_system.time_ticks() > BX_SCHEDULED_DIE_TIME) { - BX_ERROR (("ticks exceeded scheduled die time, quitting")); - BX_EXIT (2); - } -#endif - - BX_PIT_THIS s.total_usec += usec_delta; - ticks_delta=(Bit32u)((USEC_TO_TICKS((Bit64u)(BX_PIT_THIS s.total_usec)))-BX_PIT_THIS s.total_ticks); - BX_PIT_THIS s.total_ticks += ticks_delta; - - while ((BX_PIT_THIS s.total_ticks >= TICKS_PER_SECOND) && (BX_PIT_THIS s.total_usec >= USEC_PER_SECOND)) { - BX_PIT_THIS s.total_ticks -= TICKS_PER_SECOND; - BX_PIT_THIS s.total_usec -= USEC_PER_SECOND; - } - - while(ticks_delta>0) { - Bit32u maxchange=BX_PIT_THIS s.timer.get_next_event_time(); - Bit32u timedelta=maxchange; - if((maxchange==0) || (maxchange>ticks_delta)) { - timedelta=ticks_delta; - } - BX_PIT_THIS s.timer.clock_all(timedelta); - if ( (prev_timer0_out==0) ) { - if ((BX_PIT_THIS s.timer.read_OUT(0))==1) { -#ifndef BX_VMX_PIT - DEV_pic_raise_irq(0); -#endif - prev_timer0_out=1; - } - } else { - if ((BX_PIT_THIS s.timer.read_OUT(0))==0) { -#ifndef BX_VMX_PIT - DEV_pic_lower_irq(0); -#endif - prev_timer0_out=0; - } - } - prev_timer0_out=BX_PIT_THIS s.timer.read_OUT(0); - ticks_delta-=timedelta; - } - - return(want_interrupt); -} - -#endif // #if BX_USE_NEW_PIT diff --git a/tools/ioemu/iodev/pit_wrap.h b/tools/ioemu/iodev/pit_wrap.h deleted file mode 100644 index e45e1e6b57..0000000000 --- a/tools/ioemu/iodev/pit_wrap.h +++ /dev/null @@ -1,104 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: pit_wrap.h,v 1.17 2003/08/19 00:10:38 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -#ifndef _BX_PIT_WRAP_H -#define _BX_PIT_WRAP_H - -#include "bochs.h" - -#if BX_USE_NEW_PIT - -#include "pit82c54.h" - -#if BX_USE_PIT_SMF -# define BX_PIT_SMF static -# define BX_PIT_THIS bx_pit. -#else -# define BX_PIT_SMF -# define BX_PIT_THIS this-> -#endif - -#ifdef OUT -# undef OUT -#endif - -class bx_pit_c : public logfunctions { -public: - bx_pit_c( void ); - ~bx_pit_c( void ); - BX_PIT_SMF int init( void ); - BX_PIT_SMF void reset( unsigned type); - BX_PIT_SMF bx_bool periodic( Bit32u usec_delta ); - - BX_PIT_SMF int SaveState( class state_file *fd ); - BX_PIT_SMF int LoadState( class state_file *fd ); - -private: - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); -#if !BX_USE_PIT_SMF - Bit32u read( Bit32u addr, unsigned int len ); - void write( Bit32u addr, Bit32u Value, unsigned int len ); -#endif - - struct s_type { - pit_82C54 timer; - Bit8u speaker_data_on; - bx_bool refresh_clock_div2; - int timer_handle[3]; - Bit64u last_usec; - Bit32u last_next_event_time; - Bit64u total_ticks; - Bit64u usec_per_second; - Bit64u ticks_per_second; - Bit64u total_sec; - Bit64u last_time; - Bit64u last_sec_usec; - Bit64u max_ticks; - Bit64u stored_delta; - Bit64u total_usec; - Bit64u em_last_realtime; - Bit64u last_realtime_delta; - Bit64u last_realtime_ticks; - } s; - - static void timer_handler(void *this_ptr); - BX_PIT_SMF void handle_timer(); - - BX_PIT_SMF void write_count_reg( Bit8u value, unsigned timerid ); - BX_PIT_SMF Bit8u read_counter( unsigned timerid ); - BX_PIT_SMF void latch( unsigned timerid ); - BX_PIT_SMF void set_GATE(unsigned pit_id, unsigned value); - BX_PIT_SMF void start(unsigned timerid); - - BX_PIT_SMF void second_update_data(void); -}; - -extern bx_pit_c bx_pit; - -#endif // #if BX_USE_NEW_PIT -#endif // #ifndef _BX_PIT_WRAP_H diff --git a/tools/ioemu/iodev/plugin.cc b/tools/ioemu/iodev/plugin.cc deleted file mode 100644 index 136065d9d8..0000000000 --- a/tools/ioemu/iodev/plugin.cc +++ /dev/null @@ -1,554 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: plugin.cc,v 1.8 2003/07/31 12:04:47 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// This file defines the plugin and plugin-device registration functions and -// the device registration functions. It handles dynamic loading of modules, -// using the LTDL library for cross-platform support. -// -// This file is based on the plugin.c file from plex86, but with significant -// changes to make it work in Bochs. -// Plex86 is Copyright (C) 1999-2000 The plex86 developers team -// -///////////////////////////////////////////////////////////////////////// - -#include "bochs.h" -#include "plugin.h" - -#define LOG_THIS genlog-> - -#define PLUGIN_INIT_FMT_STRING "lib%s_LTX_plugin_init" -#define PLUGIN_FINI_FMT_STRING "lib%s_LTX_plugin_fini" -#define PLUGIN_PATH "" - -#ifndef WIN32 -#define PLUGIN_FILENAME_FORMAT "libbx_%s.la" -#else -#define PLUGIN_FILENAME_FORMAT "bx_%s.dll" -#endif - - - -void (*pluginRegisterIRQ)(unsigned irq, const char* name) = 0; -void (*pluginUnregisterIRQ)(unsigned irq, const char* name) = 0; - -void (* pluginResetSignal)(unsigned sig) = 0; - -void (*pluginSetHRQ)(unsigned val) = 0; -void (*pluginSetHRQHackCallback)( void (*callback)(void) ) = 0; - -int (*pluginRegisterIOReadHandler)(void *thisPtr, ioReadHandler_t callback, - unsigned base, const char *name, Bit8u mask) = 0; -int (*pluginRegisterIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback, - unsigned base, const char *name, Bit8u mask) = 0; -int (*pluginRegisterDefaultIOReadHandler)(void *thisPtr, ioReadHandler_t callback, - const char *name, Bit8u mask) = 0; -int (*pluginRegisterDefaultIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback, - const char *name, Bit8u mask) = 0; -int (*pluginRegisterTimer)(void *this_ptr, void (*funct)(void *), - Bit32u useconds, bx_bool continuous, - bx_bool active, const char* name) = 0; -void (*pluginActivateTimer)(unsigned id, Bit32u usec, bx_bool continuous) = 0; - -void (*pluginHRQHackCallback)(void); -unsigned pluginHRQ = 0; - -plugin_t *plugins = NULL; /* Head of the linked list of plugins */ -#if BX_PLUGINS -static void plugin_init_one(plugin_t *plugin); -#endif - -device_t *devices = NULL; /* Head of the linked list of registered devices */ - -plugin_t *current_plugin_context = NULL; - -/************************************************************************/ -/* Builtins declarations */ -/************************************************************************/ - - static void -builtinRegisterIRQ(unsigned irq, const char* name) -{ -#if 0 - pluginlog->panic("builtinRegisterIRQ called, no pic plugin loaded?"); -#else - bx_devices.register_irq(irq, name); -#endif -} - - static void -builtinUnregisterIRQ(unsigned irq, const char* name) -{ -#if 0 - pluginlog->panic("builtinUnregisterIRQ called, no pic plugin loaded?"); -#else - bx_devices.unregister_irq(irq, name); -#endif -} - - static void -builtinSetHRQ(unsigned val) -{ -#if 0 - pluginlog->panic("builtinSetHRQ called, no plugin loaded?"); -#else - pluginHRQ = val; -#endif -} - - static void -builtinSetHRQHackCallback( void (*callback)(void) ) -{ -#if 0 - pluginlog->panic("builtinSetHRQHackCallback called, no plugin loaded?"); -#else - pluginHRQHackCallback = callback; -#endif -} - - static void -builtinResetSignal( unsigned ) -{ - pluginlog->panic("builtinResetSignal called, no plugin loaded?"); -} - - static int -builtinRegisterIOReadHandler(void *thisPtr, ioReadHandler_t callback, - unsigned base, const char *name, Bit8u mask) -{ - BX_ASSERT (mask<8); - bx_devices.register_io_read_handler (thisPtr, callback, base, name, mask); - pluginlog->ldebug("plugin %s registered I/O read address at %04x", name, base); - return 0; -} - - static int -builtinRegisterIOWriteHandler(void *thisPtr, ioWriteHandler_t callback, - unsigned base, const char *name, Bit8u mask) -{ - BX_ASSERT (mask<8); - bx_devices.register_io_write_handler (thisPtr, callback, base, name, mask); - pluginlog->ldebug("plugin %s registered I/O write address at %04x", name, base); - return 0; -} - - static int -builtinRegisterDefaultIOReadHandler(void *thisPtr, ioReadHandler_t callback, - const char *name, Bit8u mask) -{ - BX_ASSERT (mask<8); - bx_devices.register_default_io_read_handler (thisPtr, callback, name, mask); - pluginlog->ldebug("plugin %s registered default I/O read ", name); - return 0; -} - - static int -builtinRegisterDefaultIOWriteHandler(void *thisPtr, ioWriteHandler_t callback, - const char *name, Bit8u mask) -{ - BX_ASSERT (mask<8); - bx_devices.register_default_io_write_handler (thisPtr, callback, name, mask); - pluginlog->ldebug("plugin %s registered default I/O write ", name); - return 0; -} - - static int -builtinRegisterTimer(void *this_ptr, void (*funct)(void *), - Bit32u useconds, bx_bool continuous, - bx_bool active, const char* name) -{ - int id = bx_pc_system.register_timer (this_ptr, funct, useconds, continuous, active, name); - pluginlog->ldebug("plugin %s registered timer %d", name, id); - return id; -} - - static void -builtinActivateTimer(unsigned id, Bit32u usec, bx_bool continuous) -{ - bx_pc_system.activate_timer (id, usec, continuous); - pluginlog->ldebug("plugin activated timer %d", id); -} - -#if BX_PLUGINS -/************************************************************************/ -/* Plugin initialization / deinitialization */ -/************************************************************************/ - - void -plugin_init_all (void) -{ - plugin_t *plugin; - - pluginlog->info("Initializing plugins"); - - for (plugin = plugins; plugin; plugin = plugin->next) - { - char *arg_ptr = plugin->args; - - /* process the command line */ - plugin->argc = 0; - while (plugin->argc < MAX_ARGC) - { - while (*arg_ptr && isspace (*arg_ptr)) - arg_ptr++; - - if (!*arg_ptr) - break; - plugin->argv[plugin->argc++] = arg_ptr; - - while (*arg_ptr && !isspace (*arg_ptr)) - arg_ptr++; - - if (!*arg_ptr) - break; - *arg_ptr++ = '\0'; - } - - /* initialize the plugin */ - if (plugin->plugin_init (plugin, plugin->type, plugin->argc, plugin->argv)) - { - pluginlog->panic("Plugin initialization failed for %s", plugin->name); - plugin_abort(); - } - - plugin->initialized = 1; - } - - return; -} - -void -plugin_init_one(plugin_t *plugin) -{ - char *arg_ptr = plugin->args; - - /* process the command line */ - plugin->argc = 0; - while (plugin->argc < MAX_ARGC) - { - while (*arg_ptr && isspace (*arg_ptr)) - arg_ptr++; - - if (!*arg_ptr) - break; - plugin->argv[plugin->argc++] = arg_ptr; - - while (*arg_ptr && !isspace (*arg_ptr)) - arg_ptr++; - - if (!*arg_ptr) - break; - *arg_ptr++ = '\0'; - } - - /* initialize the plugin */ - if (plugin->plugin_init (plugin, plugin->type, plugin->argc, plugin->argv)) - { - pluginlog->info("Plugin initialization failed for %s", plugin->name); - plugin_abort(); - } - - plugin->initialized = 1; -} - - - plugin_t * -plugin_unload(plugin_t *plugin) -{ - plugin_t *dead_plug; - - if (plugin->initialized) - plugin->plugin_fini (); - - lt_dlclose (plugin->handle); - free (plugin->name); - free (plugin->args); - - dead_plug = plugin; - plugin = plugin->next; - free (dead_plug); - - return plugin; -} - - -void -plugin_fini_all (void) -{ - plugin_t *plugin; - - for (plugin = plugins; plugin; plugin = plugin_unload (plugin)); - - return; -} - - void -plugin_load (char *name, char *args, plugintype_t type) -{ - plugin_t *plugin; - - plugin = (plugin_t *)malloc (sizeof (plugin_t)); - if (!plugin) - { - BX_PANIC (("malloc plugin_t failed")); - } - - plugin->type = type; - plugin->name = name; - plugin->args = args; - plugin->initialized = 0; - - char plugin_filename[BX_PATHNAME_LEN], buf[BX_PATHNAME_LEN]; - sprintf (buf, PLUGIN_FILENAME_FORMAT, name); - sprintf(plugin_filename, "%s%s", PLUGIN_PATH, buf); - - // Set context so that any devices that the plugin registers will - // be able to see which plugin created them. The registration will - // be called from either dlopen (global constructors) or plugin_init. - BX_ASSERT (current_plugin_context == NULL); - current_plugin_context = plugin; - plugin->handle = lt_dlopen (plugin_filename); - BX_INFO (("lt_dlhandle is %p", plugin->handle)); - if (!plugin->handle) - { - current_plugin_context = NULL; - BX_PANIC (("dlopen failed for module '%s': %s", name, lt_dlerror ())); - free (plugin); - return; - } - - sprintf (buf, PLUGIN_INIT_FMT_STRING, name); - plugin->plugin_init = - (int (*)(struct _plugin_t *, enum plugintype_t, int, char *[])) /* monster typecast */ - lt_dlsym (plugin->handle, buf); - if (plugin->plugin_init == NULL) { - pluginlog->panic("could not find plugin_init: %s", lt_dlerror ()); - plugin_abort (); - } - - sprintf (buf, PLUGIN_FINI_FMT_STRING, name); - plugin->plugin_fini = (void (*)(void)) lt_dlsym (plugin->handle, buf); - if (plugin->plugin_init == NULL) { - pluginlog->panic("could not find plugin_fini: %s", lt_dlerror ()); - plugin_abort (); - } - pluginlog->info("loaded plugin %s",plugin_filename); - - - /* Insert plugin at the _end_ of the plugin linked list. */ - plugin->next = NULL; - - if (!plugins) - { - /* Empty list, this become the first entry. */ - plugins = plugin; - } - else - { - /* Non-empty list. Add to end. */ - plugin_t *temp = plugins; - - while (temp->next) - temp = temp->next; - - temp->next = plugin; - } - - plugin_init_one(plugin); - - // check that context didn't change. This should only happen if we - // need a reentrant plugin_load. - BX_ASSERT (current_plugin_context == plugin); - current_plugin_context = NULL; - - return; -} - -void -plugin_abort (void) -{ - pluginlog->panic("plugin load aborted"); -} - -#endif /* end of #if BX_PLUGINS */ - -/************************************************************************/ -/* Plugin system: initialisation of plugins entry points */ -/************************************************************************/ - - void -plugin_startup(void) -{ - pluginRegisterIRQ = builtinRegisterIRQ; - pluginUnregisterIRQ = builtinUnregisterIRQ; - - pluginResetSignal = builtinResetSignal; - - pluginSetHRQHackCallback = builtinSetHRQHackCallback; - pluginSetHRQ = builtinSetHRQ; - - pluginRegisterIOReadHandler = builtinRegisterIOReadHandler; - pluginRegisterIOWriteHandler = builtinRegisterIOWriteHandler; - - pluginRegisterDefaultIOReadHandler = builtinRegisterDefaultIOReadHandler; - pluginRegisterDefaultIOWriteHandler = builtinRegisterDefaultIOWriteHandler; - - pluginRegisterTimer = builtinRegisterTimer; - pluginActivateTimer = builtinActivateTimer; - -#if BX_PLUGINS - pluginlog = new logfunctions(); - pluginlog->put("PLGIN"); - pluginlog->settype(PLUGINLOG); - int status = lt_dlinit (); - if (status != 0) { - BX_ERROR (("initialization error in ltdl library (for loading plugins)")); - BX_PANIC (("error message was: %s", lt_dlerror ())); - } -#endif -} - - -/************************************************************************/ -/* Plugin system: Device registration */ -/************************************************************************/ - -void pluginRegisterDeviceDevmodel(plugin_t *plugin, plugintype_t type, bx_devmodel_c *devmodel, char *name) -{ - device_t *device; - - device = (device_t *)malloc (sizeof (device_t)); - if (!device) - { - pluginlog->panic("can't allocate device_t"); - } - - device->name = name; - BX_ASSERT (devmodel != NULL); - device->devmodel = devmodel; - device->plugin = plugin; // this can be NULL - device->use_devmodel_interface = 1; - device->device_init_mem = NULL; // maybe should use 1 to detect any use? - device->device_init_dev = NULL; - device->device_reset = NULL; - device->device_load_state = NULL; - device->device_save_state = NULL; - device->next = NULL; - - // Don't add every kind of device to the list. - switch (type) { - case PLUGTYPE_CORE: - // Core devices are present whether or not we are using plugins, so - // they are managed by the same code in iodev/devices.cc whether - // plugins are on or off. - return; // Do not add core devices to the devices list. - case PLUGTYPE_OPTIONAL: - case PLUGTYPE_USER: - default: - // The plugin system will manage optional and user devices only. - break; - } - - if (!devices) - { - /* Empty list, this become the first entry. */ - devices = device; - } - else - { - /* Non-empty list. Add to end. */ - device_t *temp = devices; - - while (temp->next) - temp = temp->next; - - temp->next = device; - } -} - -/************************************************************************/ -/* Plugin system: Check if a plugin is loaded */ -/************************************************************************/ - -bx_bool pluginDevicePresent(char *name) -{ - device_t *device; - - for (device = devices; device; device = device->next) - { - if (strcmp(device->name,name)==0) return true; - } - - return false; -} - -#if BX_PLUGINS -/************************************************************************/ -/* Plugin system: Load one plugin */ -/************************************************************************/ - -int bx_load_plugin (const char *name, plugintype_t type) -{ - char *namecopy = new char[1+strlen(name)]; - strcpy (namecopy, name); - plugin_load (namecopy, "", type); - return 0; -} -#endif /* end of #if BX_PLUGINS */ - -/*************************************************************************/ -/* Plugin system: Execute init function of all registered plugin-devices */ -/*************************************************************************/ - -void bx_init_plugins() -{ - device_t *device; - - // two loops - for (device = devices; device; device = device->next) - { - if (!device->use_devmodel_interface) { - if (device->device_init_mem != NULL) { - pluginlog->info("init_mem of '%s' plugin device by function pointer",device->name); - device->device_init_mem(BX_MEM(0)); - } - } else { - pluginlog->info("init_mem of '%s' plugin device by virtual method",device->name); - device->devmodel->init_mem (BX_MEM(0)); - } - } - - for (device = devices; device; device = device->next) - { - if (!device->use_devmodel_interface) { - if (device->device_init_dev != NULL) { - pluginlog->info("init_dev of '%s' plugin device by function pointer",device->name); - device->device_init_dev(); - } - } else { - pluginlog->info("init_dev of '%s' plugin device by virtual method",device->name); - device->devmodel->init (); - } - } -} - -/**************************************************************************/ -/* Plugin system: Execute reset function of all registered plugin-devices */ -/**************************************************************************/ - -void bx_reset_plugins(unsigned signal) -{ - device_t *device; - for (device = devices; device; device = device->next) - { - if (!device->use_devmodel_interface) { - if (device->device_reset != NULL) { - pluginlog->info("reset of '%s' plugin device by function pointer",device->name); - device->device_reset(signal); - } - } else { - pluginlog->info("reset of '%s' plugin device by virtual method",device->name); - device->devmodel->reset (signal); - } - } -} diff --git a/tools/ioemu/iodev/scancodes.cc b/tools/ioemu/iodev/scancodes.cc deleted file mode 100644 index 63efed45f6..0000000000 --- a/tools/ioemu/iodev/scancodes.cc +++ /dev/null @@ -1,770 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: scancodes.cc,v 1.5 2002/10/24 21:07:51 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#include "scancodes.h" - -unsigned char translation8042[256] = { - 0xff,0x43,0x41,0x3f,0x3d,0x3b,0x3c,0x58,0x64,0x44,0x42,0x40,0x3e,0x0f,0x29,0x59, - 0x65,0x38,0x2a,0x70,0x1d,0x10,0x02,0x5a,0x66,0x71,0x2c,0x1f,0x1e,0x11,0x03,0x5b, - 0x67,0x2e,0x2d,0x20,0x12,0x05,0x04,0x5c,0x68,0x39,0x2f,0x21,0x14,0x13,0x06,0x5d, - 0x69,0x31,0x30,0x23,0x22,0x15,0x07,0x5e,0x6a,0x72,0x32,0x24,0x16,0x08,0x09,0x5f, - 0x6b,0x33,0x25,0x17,0x18,0x0b,0x0a,0x60,0x6c,0x34,0x35,0x26,0x27,0x19,0x0c,0x61, - 0x6d,0x73,0x28,0x74,0x1a,0x0d,0x62,0x6e,0x3a,0x36,0x1c,0x1b,0x75,0x2b,0x63,0x76, - 0x55,0x56,0x77,0x78,0x79,0x7a,0x0e,0x7b,0x7c,0x4f,0x7d,0x4b,0x47,0x7e,0x7f,0x6f, - 0x52,0x53,0x50,0x4c,0x4d,0x48,0x01,0x45,0x57,0x4e,0x51,0x4a,0x37,0x49,0x46,0x54, - 0x80,0x81,0x82,0x41,0x54,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, - 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, - 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, - 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, - 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, - 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, - 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, - 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff - }; - - -// Definition of scancodes make and break, -// for each set (mf1/xt , mf2/at , mf3/ps2) -// The table must be in BX_KEY order -// -scancode scancodes[BX_KEY_NBKEYS][3] = -{ - { // BX_KEY_CTRL_L ( ibm 58) - { "\x1D" , "\x9D" }, - { "\x14" , "\xF0\x14" }, - { "\x11" , "\xF0\x11" }, - }, - - { // BX_KEY_SHIFT_L ( ibm 44) - { "\x2A" , "\xAA" }, - { "\x12" , "\xF0\x12" }, - { "\x12" , "\xF0\x12" }, - }, - - { // BX_KEY_F1 ( ibm 112 ) - { "\x3B" , "\xBB" }, - { "\x05" , "\xF0\x05" }, - { "\x07" , "\xF0\x07" }, - }, - - { // BX_KEY_F2 ( ibm 113 ) - { "\x3C" , "\xBC" }, - { "\x06" , "\xF0\x06" }, - { "\x0F" , "\xF0\x0F" }, - }, - - { // BX_KEY_F3 ( ibm 114 ) - { "\x3D" , "\xBD" }, - { "\x04" , "\xF0\x04" }, - { "\x17" , "\xF0\x17" }, - }, - - { // BX_KEY_F4 ( ibm 115 ) - { "\x3E" , "\xBE" }, - { "\x0C" , "\xF0\x0C" }, - { "\x1F" , "\xF0\x1F" }, - }, - - { // BX_KEY_F5 ( ibm 116 ) - { "\x3F" , "\xBF" }, - { "\x03" , "\xF0\x03" }, - { "\x27" , "\xF0\x27" }, - }, - - { // BX_KEY_F6 ( ibm 117 ) - { "\x40" , "\xC0" }, - { "\x0B" , "\xF0\x0B" }, - { "\x2F" , "\xF0\x2F" }, - }, - - { // BX_KEY_F7 ( ibm 118 ) - { "\x41" , "\xC1" }, - { "\x83" , "\xF0\x83" }, - { "\x37" , "\xF0\x37" }, -}, - - { // BX_KEY_F8 ( ibm 119 ) - { "\x42" , "\xC2" }, - { "\x0A" , "\xF0\x0A" }, - { "\x3F" , "\xF0\x3F" }, - }, - - { // BX_KEY_F9 ( ibm 120 ) - { "\x43" , "\xC3" }, - { "\x01" , "\xF0\x01" }, - { "\x47" , "\xF0\x47" }, - }, - - { // BX_KEY_F10 ( ibm 121 ) - { "\x44" , "\xC4" }, - { "\x09" , "\xF0\x09" }, - { "\x4F" , "\xF0\x4F" }, - }, - - { // BX_KEY_F11 ( ibm 122 ) - { "\x57" , "\xD7" }, - { "\x78" , "\xF0\x78" }, - { "\x56" , "\xF0\x56" }, - }, - - { // BX_KEY_F12 ( ibm 123 ) - { "\x58" , "\xD8" }, - { "\x07" , "\xF0\x07" }, - { "\x5E" , "\xF0\x5E" }, - }, - - { // BX_KEY_CTRL_R ( ibm 64 ) - { "\xE0\x1D" , "\xE0\x9D" }, - { "\xE0\x14" , "\xE0\xF0\x14" }, - { "\x58" , "\xF0x58" }, - }, - - { // BX_KEY_SHIFT_R ( ibm 57 ) - { "\x36" , "\xB6" }, - { "\x59" , "\xF0\x59" }, - { "\x59" , "\xF0\x59" }, - }, - - { // BX_KEY_CAPS_LOCK ( ibm 30 ) - { "\x3A" , "\xBA" }, - { "\x58" , "\xF0\x58" }, - { "\x14" , "\xF0\x14" }, - }, - - { // BX_KEY_NUM_LOCK ( ibm 90 ) - { "\x45" , "\xC5" }, - { "\x77" , "\xF0\x77" }, - { "\x76" , "\xF0\x76" }, - }, - - { // BX_KEY_ALT_L ( ibm 60 ) - { "\x38" , "\xB8" }, - { "\x11" , "\xF0\x11" }, - { "\x19" , "\xF0\x19" }, - }, - - { // BX_KEY_ALT_R ( ibm 62 ) - { "\xE0\x38" , "\xE0\xB8" }, - { "\xE0\x11" , "\xE0\xF0\x11" }, - { "\x39" , "\xF0\x39" }, - }, - - { // BX_KEY_A ( ibm 31 ) - { "\x1E" , "\x9E" }, - { "\x1C" , "\xF0\x1C" }, - { "\x1C" , "\xF0\x1C" }, - }, - - { // BX_KEY_B ( ibm 50 ) - { "\x30" , "\xB0" }, - { "\x32" , "\xF0\x32" }, - { "\x32" , "\xF0\x32" }, - }, - - { // BX_KEY_C ( ibm 48 ) - { "\x2E" , "\xAE" }, - { "\x21" , "\xF0\x21" }, - { "\x21" , "\xF0\x21" }, - }, - - { // BX_KEY_D ( ibm 33 ) - { "\x20" , "\xA0" }, - { "\x23" , "\xF0\x23" }, - { "\x23" , "\xF0\x23" }, - }, - - { // BX_KEY_E ( ibm 19 ) - { "\x12" , "\x92" }, - { "\x24" , "\xF0\x24" }, - { "\x24" , "\xF0\x24" }, - }, - - { // BX_KEY_F ( ibm 34 ) - { "\x21" , "\xA1" }, - { "\x2B" , "\xF0\x2B" }, - { "\x2B" , "\xF0\x2B" }, - }, - - { // BX_KEY_G ( ibm 35 ) - { "\x22" , "\xA2" }, - { "\x34" , "\xF0\x34" }, - { "\x34" , "\xF0\x34" }, - }, - - { // BX_KEY_H ( ibm 36 ) - { "\x23" , "\xA3" }, - { "\x33" , "\xF0\x33" }, - { "\x33" , "\xF0\x33" }, - }, - - { // BX_KEY_I ( ibm 24 ) - { "\x17" , "\x97" }, - { "\x43" , "\xF0\x43" }, - { "\x43" , "\xF0\x43" }, - }, - - { // BX_KEY_J ( ibm 37 ) - { "\x24" , "\xA4" }, - { "\x3B" , "\xF0\x3B" }, - { "\x3B" , "\xF0\x3B" }, - }, - - { // BX_KEY_K ( ibm 38 ) - { "\x25" , "\xA5" }, - { "\x42" , "\xF0\x42" }, - { "\x42" , "\xF0\x42" }, - }, - - { // BX_KEY_L ( ibm 39 ) - { "\x26" , "\xA6" }, - { "\x4B" , "\xF0\x4B" }, - { "\x4B" , "\xF0\x4B" }, - }, - - { // BX_KEY_M ( ibm 52 ) - { "\x32" , "\xB2" }, - { "\x3A" , "\xF0\x3A" }, - { "\x3A" , "\xF0\x3A" }, - }, - - { // BX_KEY_N ( ibm 51 ) - { "\x31" , "\xB1" }, - { "\x31" , "\xF0\x31" }, - { "\x31" , "\xF0\x31" }, - }, - - { // BX_KEY_O ( ibm 25 ) - { "\x18" , "\x98" }, - { "\x44" , "\xF0\x44" }, - { "\x44" , "\xF0\x44" }, - }, - - { // BX_KEY_P ( ibm 26 ) - { "\x19" , "\x99" }, - { "\x4D" , "\xF0\x4D" }, - { "\x4D" , "\xF0\x4D" }, - }, - - { // BX_KEY_Q ( ibm 17 ) - { "\x10" , "\x90" }, - { "\x15" , "\xF0\x15" }, - { "\x15" , "\xF0\x15" }, - }, - - { // BX_KEY_R ( ibm 20 ) - { "\x13" , "\x93" }, - { "\x2D" , "\xF0\x2D" }, - { "\x2D" , "\xF0\x2D" }, - }, - - { // BX_KEY_S ( ibm 32 ) - { "\x1F" , "\x9F" }, - { "\x1B" , "\xF0\x1B" }, - { "\x1B" , "\xF0\x1B" }, - }, - - { // BX_KEY_T ( ibm 21 ) - { "\x14" , "\x94" }, - { "\x2C" , "\xF0\x2C" }, - { "\x2C" , "\xF0\x2C" }, - }, - - { // BX_KEY_U ( ibm 23 ) - { "\x16" , "\x96" }, - { "\x3C" , "\xF0\x3C" }, - { "\x3C" , "\xF0\x3C" }, - }, - - { // BX_KEY_V ( ibm 49 ) - { "\x2F" , "\xAF" }, - { "\x2A" , "\xF0\x2A" }, - { "\x2A" , "\xF0\x2A" }, - }, - - { // BX_KEY_W ( ibm 18 ) - { "\x11" , "\x91" }, - { "\x1D" , "\xF0\x1D" }, - { "\x1D" , "\xF0\x1D" }, - }, - - { // BX_KEY_X ( ibm 47 ) - { "\x2D" , "\xAD" }, - { "\x22" , "\xF0\x22" }, - { "\x22" , "\xF0\x22" }, - }, - - { // BX_KEY_Y ( ibm 22 ) - { "\x15" , "\x95" }, - { "\x35" , "\xF0\x35" }, - { "\x35" , "\xF0\x35" }, - }, - - { // BX_KEY_Z ( ibm 46 ) - { "\x2C" , "\xAC" }, - { "\x1A" , "\xF0\x1A" }, - { "\x1A" , "\xF0\x1A" }, - }, - - { // BX_KEY_0 ( ibm 11 ) - { "\x0B" , "\x8B" }, - { "\x45" , "\xF0\x45" }, - { "\x45" , "\xF0\x45" }, - }, - - { // BX_KEY_1 ( ibm 2 ) - { "\x02" , "\x82" }, - { "\x16" , "\xF0\x16" }, - { "\x16" , "\xF0\x16" }, - }, - - { // BX_KEY_2 ( ibm 3 ) - { "\x03" , "\x83" }, - { "\x1E" , "\xF0\x1E" }, - { "\x1E" , "\xF0\x1E" }, - }, - - { // BX_KEY_3 ( ibm 4 ) - { "\x04" , "\x84" }, - { "\x26" , "\xF0\x26" }, - { "\x26" , "\xF0\x26" }, - }, - - { // BX_KEY_4 ( ibm 5 ) - { "\x05" , "\x85" }, - { "\x25" , "\xF0\x25" }, - { "\x25" , "\xF0\x25" }, - }, - - { // BX_KEY_5 ( ibm 6 ) - { "\x06" , "\x86" }, - { "\x2E" , "\xF0\x2E" }, - { "\x2E" , "\xF0\x2E" }, - }, - - { // BX_KEY_6 ( ibm 7 ) - { "\x07" , "\x87" }, - { "\x36" , "\xF0\x36" }, - { "\x36" , "\xF0\x36" }, - }, - - { // BX_KEY_7 ( ibm 8 ) - { "\x08" , "\x88" }, - { "\x3D" , "\xF0\x3D" }, - { "\x3D" , "\xF0\x3D" }, - }, - - { // BX_KEY_8 ( ibm 9 ) - { "\x09" , "\x89" }, - { "\x3E" , "\xF0\x3E" }, - { "\x3E" , "\xF0\x3E" }, - }, - - { // BX_KEY_9 ( ibm 10 ) - { "\x0A" , "\x8A" }, - { "\x46" , "\xF0\x46" }, - { "\x46" , "\xF0\x46" }, - }, - - { // BX_KEY_ESC ( ibm 110 ) - { "\x01" , "\x81" }, - { "\x76" , "\xF0\x76" }, - { "\x08" , "\xF0\x08" }, - }, - - { // BX_KEY_SPACE ( ibm 61 ) - { "\x39" , "\xB9" }, - { "\x29" , "\xF0\x29" }, - { "\x29" , "\xF0\x29" }, - }, - - { // BX_KEY_SINGLE_QUOTE ( ibm 41 ) - { "\x28" , "\xA8" }, - { "\x52" , "\xF0\x52" }, - { "\x52" , "\xF0\x52" }, - }, - - { // BX_KEY_COMMA ( ibm 53 ) - { "\x33" , "\xB3" }, - { "\x41" , "\xF0\x41" }, - { "\x41" , "\xF0\x41" }, - }, - - { // BX_KEY_PERIOD ( ibm 54 ) - { "\x34" , "\xB4" }, - { "\x49" , "\xF0\x49" }, - { "\x49" , "\xF0\x49" }, - }, - - { // BX_KEY_SLASH ( ibm 55 ) - { "\x35" , "\xB5" }, - { "\x4A" , "\xF0\x4A" }, - { "\x4A" , "\xF0\x4A" }, - }, - - { // BX_KEY_SEMICOLON ( ibm 40 ) - { "\x27" , "\xA7" }, - { "\x4C" , "\xF0\x4C" }, - { "\x4C" , "\xF0\x4C" }, - }, - - { // BX_KEY_EQUALS ( ibm 13 ) - { "\x0D" , "\x8D" }, - { "\x55" , "\xF0\x55" }, - { "\x55" , "\xF0\x55" }, - }, - - { // BX_KEY_LEFT_BRACKET ( ibm 27 ) - { "\x1A" , "\x9A" }, - { "\x54" , "\xF0\x54" }, - { "\x54" , "\xF0\x54" }, - }, - - { // BX_KEY_BACKSLASH ( ibm 42, 29) - { "\x2B" , "\xAB" }, - { "\x5D" , "\xF0\x5D" }, - { "\x53" , "\xF0\x53" }, - }, - - { // BX_KEY_RIGHT_BRACKET ( ibm 28 ) - { "\x1B" , "\x9B" }, - { "\x5B" , "\xF0\x5B" }, - { "\x5B" , "\xF0\x5B" }, - }, - - { // BX_KEY_MINUS ( ibm 12 ) - { "\x0C" , "\x8C" }, - { "\x4E" , "\xF0\x4E" }, - { "\x4E" , "\xF0\x4E" }, - }, - - { // BX_KEY_GRAVE ( ibm 1 ) - { "\x29" , "\xA9" }, - { "\x0E" , "\xF0\x0E" }, - { "\x0E" , "\xF0\x0E" }, - }, - - { // BX_KEY_BACKSPACE ( ibm 15 ) - { "\x0E" , "\x8E" }, - { "\x66" , "\xF0\x66" }, - { "\x66" , "\xF0\x66" }, - }, - - { // BX_KEY_ENTER ( ibm 43 ) - { "\x1C" , "\x9C" }, - { "\x5A" , "\xF0\x5A" }, - { "\x5A" , "\xF0\x5A" }, - }, - - { // BX_KEY_TAB ( ibm 16 ) - { "\x0F" , "\x8F" }, - { "\x0D" , "\xF0\x0D" }, - { "\x0D" , "\xF0\x0D" }, - }, - - { // BX_KEY_LEFT_BACKSLASH ( ibm 45 ) - { "\x56" , "\xD6" }, - { "\x61" , "\xF0\x61" }, - { "\x13" , "\xF0\x13" }, - }, - - { // BX_KEY_PRINT ( ibm 124 ) - { "\xE0\x37" , "\xE0\xB7" }, - { "\xE0\x7C" , "\xE0\xF0\x7C" }, - { "\x57" , "\xF0\x57" }, - }, - - { // BX_KEY_SCRL_LOCK ( ibm 125 ) - { "\x46" , "\xC6" }, - { "\x7E" , "\xF0\x7E" }, - { "\x5F" , "\xF0\x5F" }, - }, - - { // BX_KEY_PAUSE ( ibm 126 ) - { "\xE1\x1D\x45\xE1\x9D\xC5" , "" }, - { "\xE1\x14\x77\xE1\xF0\x14\xF0\x77" , "" }, - { "\x62" , "\xF0\x62" }, - }, - - { // BX_KEY_INSERT ( ibm 75 ) - { "\xE0\x52" , "\xE0\xD2" }, - { "\xE0\x70" , "\xE0\xF0\x70" }, - { "\x67" , "\xF0\x67" }, - }, - - { // BX_KEY_DELETE ( ibm 76 ) - { "\xE0\x53" , "\xE0\xD3" }, - { "\xE0\x71" , "\xE0\xF0\x71" }, - { "\x64" , "\xF0\x64" }, - }, - - { // BX_KEY_HOME ( ibm 80 ) - { "\xE0\x47" , "\xE0\xC7" }, - { "\xE0\x6C" , "\xE0\xF0\x6C" }, - { "\x6E" , "\xF0\x6E" }, - }, - - { // BX_KEY_END ( ibm 81 ) - { "\xE0\x4F" , "\xE0\xCF" }, - { "\xE0\x69" , "\xE0\xF0\x69" }, - { "\x65" , "\xF0\x65" }, - }, - - { // BX_KEY_PAGE_UP ( ibm 85 ) - { "\xE0\x49" , "\xE0\xC9" }, - { "\xE0\x7D" , "\xE0\xF0\x7D" }, - { "\x6F" , "\xF0\x6F" }, - }, - - { // BX_KEY_PAGE_DOWN ( ibm 86 ) - { "\xE0\x51" , "\xE0\xD1" }, - { "\xE0\x7A" , "\xE0\xF0\x7A" }, - { "\x6D" , "\xF0\x6D" }, - }, - - { // BX_KEY_KP_ADD ( ibm 106 ) - { "\x4E" , "\xCE" }, - { "\x79" , "\xF0\x79" }, - { "\x7C" , "\xF0\x7C" }, - }, - - { // BX_KEY_KP_SUBTRACT ( ibm 105 ) - { "\x4A" , "\xCA" }, - { "\x7B" , "\xF0\x7B" }, - { "\x84" , "\xF0\x84" }, - }, - - { // BX_KEY_KP_END ( ibm 93 ) - { "\x4F" , "\xCF" }, - { "\x69" , "\xF0\x69" }, - { "\x69" , "\xF0\x69" }, - }, - - { // BX_KEY_KP_DOWN ( ibm 98 ) - { "\x50" , "\xD0" }, - { "\x72" , "\xF0\x72" }, - { "\x72" , "\xF0\x72" }, - }, - - { // BX_KEY_KP_PAGE_DOWN ( ibm 103 ) - { "\x51" , "\xD1" }, - { "\x7A" , "\xF0\x7A" }, - { "\x7A" , "\xF0\x7A" }, - }, - - { // BX_KEY_KP_LEFT ( ibm 92 ) - { "\x4B" , "\xCB" }, - { "\x6B" , "\xF0\x6B" }, - { "\x6B" , "\xF0\x6B" }, - }, - - { // BX_KEY_KP_RIGHT ( ibm 102 ) - { "\x4D" , "\xCD" }, - { "\x74" , "\xF0\x74" }, - { "\x74" , "\xF0\x74" }, - }, - - { // BX_KEY_KP_HOME ( ibm 91 ) - { "\x47" , "\xC7" }, - { "\x6C" , "\xF0\x6C" }, - { "\x6C" , "\xF0\x6C" }, - }, - - { // BX_KEY_KP_UP ( ibm 96 ) - { "\x48" , "\xC8" }, - { "\x75" , "\xF0\x75" }, - { "\x75" , "\xF0\x75" }, - }, - - { // BX_KEY_KP_PAGE_UP ( ibm 101 ) - { "\x49" , "\xC9" }, - { "\x7D" , "\xF0\x7D" }, - { "\x7D" , "\xF0\x7D" }, - }, - - { // BX_KEY_KP_INSERT ( ibm 99 ) - { "\x52" , "\xD2" }, - { "\x70" , "\xF0\x70" }, - { "\x70" , "\xF0\x70" }, - }, - - { // BX_KEY_KP_DELETE ( ibm 104 ) - { "\x53" , "\xD3" }, - { "\x71" , "\xF0\x71" }, - { "\x71" , "\xF0\x71" }, - }, - - { // BX_KEY_KP_5 ( ibm 97 ) - { "\x4C" , "\xCC" }, - { "\x73" , "\xF0\x73" }, - { "\x73" , "\xF0\x73" }, - }, - - { // BX_KEY_UP ( ibm 83 ) - { "\xE0\x48" , "\xE0\xC8" }, - { "\xE0\x75" , "\xE0\xF0\x75" }, - { "\x63" , "\xF0\x63" }, - }, - - { // BX_KEY_DOWN ( ibm 84 ) - { "\xE0\x50" , "\xE0\xD0" }, - { "\xE0\x72" , "\xE0\xF0\x72" }, - { "\x60" , "\xF0\x60" }, - }, - - { // BX_KEY_LEFT ( ibm 79 ) - { "\xE0\x4B" , "\xE0\xCB" }, - { "\xE0\x6B" , "\xE0\xF0\x6B" }, - { "\x61" , "\xF0\x61" }, - }, - - { // BX_KEY_RIGHT ( ibm 89 ) - { "\xE0\x4D" , "\xE0\xCD" }, - { "\xE0\x74" , "\xE0\xF0\x74" }, - { "\x6A" , "\xF0\x6A" }, - }, - - { // BX_KEY_KP_ENTER ( ibm 108 ) - { "\xE0\x1C" , "\xE0\x9C" }, - { "\xE0\x5A" , "\xE0\xF0\x5A" }, - { "\x79" , "\xF0\x79" }, - }, - - { // BX_KEY_KP_MULTIPLY ( ibm 100 ) - { "\x37" , "\xB7" }, - { "\x7C" , "\xF0\x7C" }, - { "\x7E" , "\xF0\x7E" }, - }, - - { // BX_KEY_KP_DIVIDE ( ibm 95 ) - { "\xE0\x35" , "\xE0\xB5" }, - { "\xE0\x4A" , "\xE0\xF0\x4A" }, - { "\x77" , "\xF0\x77" }, - }, - - { // BX_KEY_WIN_L - { "\xE0\x5B" , "\xE0\xDB" }, - { "\xE0\x1F" , "\xE0\xF0\x1F" }, - { "\x8B" , "\xF0\x8B" }, - }, - - { // BX_KEY_WIN_R - { "\xE0\x5C" , "\xE0\xDC" }, - { "\xE0\x27" , "\xE0\xF0\x27" }, - { "\x8C" , "\xF0\x8C" }, - }, - - { // BX_KEY_MENU - { "\xE0\x5D" , "\xE0\xDD" }, - { "\xE0\x2F" , "\xE0\xF0\x2F" }, - { "\x8D" , "\xF0\x8D" }, - }, - - { // BX_KEY_ALT_SYSREQ - { "\x54" , "\xD4" }, - { "\x84" , "\xF0\x84" }, - { "\x57" , "\xF0\x57" }, - }, - - { // BX_KEY_CTRL_BREAK - { "\xE0\x46" , "\xE0\xC6" }, - { "\xE0\x7E" , "\xE0\xF0\x7E" }, - { "\x62" , "\xF0\x62" }, - }, - - { // BX_KEY_INT_BACK - { "\xE0\x6A" , "\xE0\xEA" }, - { "\xE0\x38" , "\xE0\xF0\x38" }, - { "\x38" , "\xF0\x38" }, - }, - - { // BX_KEY_INT_FORWARD - { "\xE0\x69" , "\xE0\xE9" }, - { "\xE0\x30" , "\xE0\xF0\x30" }, - { "\x30" , "\xF0\x30" }, - }, - - { // BX_KEY_INT_STOP - { "\xE0\x68" , "\xE0\xE8" }, - { "\xE0\x28" , "\xE0\xF0\x28" }, - { "\x28" , "\xF0\x28" }, - }, - - { // BX_KEY_INT_MAIL - { "\xE0\x6C" , "\xE0\xEC" }, - { "\xE0\x48" , "\xE0\xF0\x48" }, - { "\x48" , "\xF0\x48" }, - }, - - { // BX_KEY_INT_SEARCH - { "\xE0\x65" , "\xE0\xE5" }, - { "\xE0\x10" , "\xE0\xF0\x10" }, - { "\x10" , "\xF0\x10" }, - }, - - { // BX_KEY_INT_FAV - { "\xE0\x66" , "\xE0\xE6" }, - { "\xE0\x18" , "\xE0\xF0\x18" }, - { "\x18" , "\xF0\x18" }, - }, - - { // BX_KEY_INT_HOME - { "\xE0\x32" , "\xE0\xB2" }, - { "\xE0\x3A" , "\xE0\xF0\x3A" }, - { "\x97" , "\xF0\x97" }, - }, - - { // BX_KEY_POWER_MYCOMP - { "\xE0\x6B" , "\xE0\xEB" }, - { "\xE0\x40" , "\xE0\xF0\x40" }, - { "\x40" , "\xF0\x40" }, - }, - - { // BX_KEY_POWER_CALC - { "\xE0\x21" , "\xE0\xA1" }, - { "\xE0\x2B" , "\xE0\xF0\x2B" }, - { "\x99" , "\xF0\x99" }, - }, - - { // BX_KEY_POWER_SLEEP - { "\xE0\x5F" , "\xE0\xDF" }, - { "\xE0\x3F" , "\xE0\xF0\x3F" }, - { "\x7F" , "\xF0\x7F" }, - }, - - { // BX_KEY_POWER_POWER - { "\xE0\x5E" , "\xE0\xDE" }, - { "\xE0\x37" , "\xE0\xF0\x37" }, - { "" , "" }, - }, - - { // BX_KEY_POWER_WAKE - { "\xE0\x63" , "\xE0\xE3" }, - { "\xE0\x5E" , "\xE0\xF0\x5E" }, - { "" , "" }, - }, - -}; diff --git a/tools/ioemu/iodev/scancodes.h b/tools/ioemu/iodev/scancodes.h deleted file mode 100644 index f26491b56e..0000000000 --- a/tools/ioemu/iodev/scancodes.h +++ /dev/null @@ -1,31 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: scancodes.h,v 1.4 2002/10/24 21:07:51 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -// Translation table of the 8042 -extern unsigned char translation8042[256]; - -typedef struct { - const char *make; - const char *brek; - }scancode; - -// Scancodes table -extern scancode scancodes[BX_KEY_NBKEYS][3]; diff --git a/tools/ioemu/iodev/scsi_commands.h b/tools/ioemu/iodev/scsi_commands.h deleted file mode 100644 index c516fde31c..0000000000 --- a/tools/ioemu/iodev/scsi_commands.h +++ /dev/null @@ -1,418 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: scsi_commands.h,v 1.3 2001/10/03 13:10:38 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -/* scsi/commands.h - Used only in cdrom_amigaos.cc. - - Operation codes for SCSI-2 commands - - 30 Nov 94 Peter Urbanec Created file - 10 Jan 95 Peter Urbanec Added SCSI_ prefix to all commands - 31 Jan 95 Peter Urbanec Released to public - -*/ - - -/* All device types */ - -#define SCSI_CHANGE_DEFINITION 0x40 -#define SCSI_COMPARE 0x39 -#define SCSI_COPY 0x18 -#define SCSI_COPY_AND_VERIFY 0x3a -#define SCSI_INQUIRY 0x12 -#define SCSI_LOG_SELECT 0x4c -#define SCSI_LOG_SENSE 0x4d -#define SCSI_MODE_SELECT_6 0x15 -#define SCSI_MODE_SELECT_10 0x55 -#define SCSI_MODE_SENSE_6 0x1a -#define SCSI_MODE_SENSE_10 0x5a -#define SCSI_READ_BUFFER 0x3c -#define SCSI_RECEIVE_DIAGNOSTIC_RESULTS 0x1c -#define SCSI_REQUEST_SENSE 0x03 -#define SCSI_SEND_DIAGNOSTIC 0x1d -#define SCSI_TEST_UNIT_READY 0x00 -#define SCSI_WRITE_BUFFER 0x3b - - -/* Direct Access devices */ - -#define SCSI_DA_CHANGE_DEFINITION 0x40 -#define SCSI_DA_COMPARE 0x39 -#define SCSI_DA_COPY 0x18 -#define SCSI_DA_COPY_AND_VERIFY 0x3a -#define SCSI_DA_FORMAT_UNIT 0x04 -#define SCSI_DA_INQUIRY 0x12 -#define SCSI_DA_LOCK_UNLOCK_CACHE 0x36 -#define SCSI_DA_LOG_SELECT 0x4c -#define SCSI_DA_LOG_SENSE 0x4d -#define SCSI_DA_MODE_SELECT_6 0x15 -#define SCSI_DA_MODE_SELECT_10 0x55 -#define SCSI_DA_MODE_SENSE_6 0x1a -#define SCSI_DA_MODE_SENSE_10 0x5a -#define SCSI_DA_PRE_FETCH 0x34 -#define SCSI_DA_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e -#define SCSI_DA_READ_6 0x08 -#define SCSI_DA_READ_10 0x28 -#define SCSI_DA_READ_BUFFER 0x3c -#define SCSI_DA_READ_CAPACITY 0x25 -#define SCSI_DA_READ_DEFECT_DATA 0x37 -#define SCSI_DA_READ_LONG 0x3e -#define SCSI_DA_REASSIGN_BLOCKS 0x07 -#define SCSI_DA_RECEIVE_DIAGNOSTIC_RESULTS 0x1c -#define SCSI_DA_RELEASE 0x17 -#define SCSI_DA_REQUEST_SENSE 0x03 -#define SCSI_DA_RESERVE 0x16 -#define SCSI_DA_REZERO_UNIT 0x01 -#define SCSI_DA_SEARCH_DATA_EQUAL 0x31 -#define SCSI_DA_SEARCH_DATA_HIGH 0x30 -#define SCSI_DA_SEARCH_DATA_LOW 0x32 -#define SCSI_DA_SEEK_6 0x0b -#define SCSI_DA_SEEK_10 0x2b -#define SCSI_DA_SEND_DIAGNOSTIC 0x1d -#define SCSI_DA_SET_LIMITS 0x33 -#define SCSI_DA_START_STOP_UNIT 0x1b -#define SCSI_DA_SYNCHRONIZE_CACHE 0x35 -#define SCSI_DA_TEST_UNIT_READY 0x00 -#define SCSI_DA_VERIFY 0x2f - - -/* Sequential access devices */ - -#define SCSI_SA_CHANGE_DEFINITION 0x40 -#define SCSI_SA_COMPARE 0x39 -#define SCSI_SA_COPY 0x18 -#define SCSI_SA_COPY_AND_VERIFY 0x3a -#define SCSI_SA_ERASE 0x19 -#define SCSI_SA_INQUIRY 0x12 -#define SCSI_SA_LOAD_UNLOAD 0x1b -#define SCSI_SA_LOCATE 0x2b -#define SCSI_SA_LOG_SELECT 0x4c -#define SCSI_SA_LOG_SENSE 0x4d -#define SCSI_SA_MODE_SELECT_6 0x15 -#define SCSI_SA_MODE_SELECT_10 0x55 -#define SCSI_SA_MODE_SENSE_6 0x1a -#define SCSI_SA_MODE_SENSE_10 0x5a -#define SCSI_SA_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e -#define SCSI_SA_READ 0x08 -#define SCSI_SA_READ_BLOCK_LIMITS 0x05 -#define SCSI_SA_READ_BUFFER 0x3c -#define SCSI_SA_READ_POSITION 0x34 -#define SCSI_SA_READ_REVERSE 0x0f -#define SCSI_SA_RECEIVE_DIAGNOSTIC_RESULTS 0x1c -#define SCSI_SA_RECOVER_BUFFERED_DATA 0x14 -#define SCSI_SA_RELEASE_UNIT 0x17 -#define SCSI_SA_REQUEST_SENSE 0x03 -#define SCSI_SA_RESERVE_UNIT 0x16 -#define SCSI_SA_REWIND 0x01 -#define SCSI_SA_SEND_DIAGNOSTIC 0x1d -#define SCSI_SA_SPACE 0x11 -#define SCSI_SA_TEST_UNIT_READY 0x00 -#define SCSI_SA_VERIFY 0x13 -#define SCSI_SA_WRITE 0x0a -#define SCSI_SA_WRITE_BUFFER 0x3b -#define SCSI_SA_WRITE_FILEMARKS 0x10 - - -/* Printer devices */ - -#define SCSI_PRT_CHANGE_DEFINITION 0x40 -#define SCSI_PRT_COMPARE 0x39 -#define SCSI_PRT_COPY 0x18 -#define SCSI_PRT_COPY_AND_VERIFY 0x3a -#define SCSI_PRT_FORMAT 0x04 -#define SCSI_PRT_INQUIRY 0x12 -#define SCSI_PRT_LOG_SELECT 0x4c -#define SCSI_PRT_LOG_SENSE 0x4d -#define SCSI_PRT_MODE_SELECT_6 0x15 -#define SCSI_PRT_MODE_SELECT_10 0x55 -#define SCSI_PRT_MODE_SENSE_6 0x1a -#define SCSI_PRT_MODE_SENSE_10 0x5a -#define SCSI_PRT_PRINT 0x0a -#define SCSI_PRT_READ_BUFFER 0x3c -#define SCSI_PRT_RECEIVE_DIAGNOSTIC_RESULTS 0x1c -#define SCSI_PRT_RECOVER_BUFFERED_DATA 0x14 -#define SCSI_PRT_RELEASE_UNIT 0x17 -#define SCSI_PRT_REQUEST_SENSE 0x03 -#define SCSI_PRT_RESERVE_UNIT 0x16 -#define SCSI_PRT_SEND_DIAGNOSTIC 0x1d -#define SCSI_PRT_SLEW_AND_PRINT 0x0b -#define SCSI_PRT_STOP_PRINT 0x1b -#define SCSI_PRT_SYNCHRONIZE_BUFFER 0x10 -#define SCSI_PRT_TEST_UNIT_READY 0x00 -#define SCSI_PRT_WRITE_BUFFER 0x3b - - -/* Processor devices */ - -#define SCSI_CPU_CHANGE_DEFINITION 0x40 -#define SCSI_CPU_COMPARE 0x39 -#define SCSI_CPU_COPY 0x18 -#define SCSI_CPU_COPY_AND_VERIFY 0x3a -#define SCSI_CPU_INQUIRY 0x12 -#define SCSI_CPU_LOG_SELECT 0x4c -#define SCSI_CPU_LOG_SENSE 0x4d -#define SCSI_CPU_READ_BUFFER 0x3c -#define SCSI_CPU_RECEIVE 0x08 -#define SCSI_CPU_RECEIVE_DIAGNOSTIC_RESULTS 0x1c -#define SCSI_CPU_REQUEST_SENSE 0x03 -#define SCSI_CPU_SEND 0x0a -#define SCSI_CPU_SEND_DIAGNOSTIC 0x1d -#define SCSI_CPU_TEST_UNIT_READY 0x00 -#define SCSI_CPU_WRITE_BUFFER 0x3b - - -/* Write Once devices */ - -#define SCSI_WO_CHANGE_DEFINITION 0x40 -#define SCSI_WO_COMPARE 0x39 -#define SCSI_WO_COPY 0x18 -#define SCSI_WO_COPY_AND_VERIFY 0x3a -#define SCSI_WO_INQUIRY 0x12 -#define SCSI_WO_LOCK_UNLOCK_CACHE 0x36 -#define SCSI_WO_LOG_SELECT 0x4c -#define SCSI_WO_LOG_SENSE 0x4d -#define SCSI_WO_MEDIUM_SCAN 0x38 -#define SCSI_WO_MODE_SELECT_6 0x15 -#define SCSI_WO_MODE_SELECT_10 0x55 -#define SCSI_WO_MODE_SENSE_6 0x1a -#define SCSI_WO_MODE_SENSE_10 0x5a -#define SCSI_WO_PRE_FETCH 0x34 -#define SCSI_WO_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e -#define SCSI_WO_READ_6 0x08 -#define SCSI_WO_READ_10 0x28 -#define SCSI_WO_READ_12 0xa8 -#define SCSI_WO_READ_BUFFER 0x3c -#define SCSI_WO_READ_CAPACITY 0x25 -#define SCSI_WO_READ_LONG 0x3e -#define SCSI_WO_REASSIGN_BLOCKS 0x07 -#define SCSI_WO_RECEIVE_DIAGNOSTIC_RESULTS 0x1c -#define SCSI_WO_RELEASE 0x17 -#define SCSI_WO_REQUEST_SENSE 0x03 -#define SCSI_WO_RESERVE 0x16 -#define SCSI_WO_REZERO_UNIT 0x01 -#define SCSI_WO_SEARCH_DATA_EQUAL_10 0x31 -#define SCSI_WO_SEARCH_DATA_EQUAL_12 0xb1 -#define SCSI_WO_SEARCH_DATA_HIGH_10 0x30 -#define SCSI_WO_SEARCH_DATA_HIGH_12 0xb0 -#define SCSI_WO_SEARCH_DATA_LOW_10 0x32 -#define SCSI_WO_SEARCH_DATA_LOW_12 0xb2 -#define SCSI_WO_SEEK_6 0x0b -#define SCSI_WO_SEEK_10 0x2b -#define SCSI_WO_SEND_DIAGNOSTIC 0x1d -#define SCSI_WO_SET_LIMITS_10 0x33 -#define SCSI_WO_SET_LIMITS_12 0xb3 -#define SCSI_WO_START_STOP_UNIT 0x1b -#define SCSI_WO_SYNCHRONIZE_CACHE 0x35 -#define SCSI_WO_TEST_UNIT_READY 0x00 -#define SCSI_WO_VERIFY_10 0x2f -#define SCSI_WO_VERIFY_12 0xaf -#define SCSI_WO_WRITE_6 0x0a -#define SCSI_WO_WRITE_10 0x2a -#define SCSI_WO_WRITE_12 0xaa -#define SCSI_WO_WRITE_AND_VERIFY_10 0x2e -#define SCSI_WO_WRITE_AND_VERIFY_12 0xae -#define SCSI_WO_WRITE_BUFFER 0x3b -#define SCSI_WO_WRITE_LONG 0x3f - - -/* CD-ROM devices */ - -#define SCSI_CD_CHANGE_DEFINITION 0x40 -#define SCSI_CD_COMPARE 0x39 -#define SCSI_CD_COPY 0x18 -#define SCSI_CD_COPY_AND_VERIFY 0x3a -#define SCSI_CD_INQUIRY 0x12 -#define SCSI_CD_LOCK_UNLOCK_CACHE 0x36 -#define SCSI_CD_LOG_SELECT 0x4c -#define SCSI_CD_LOG_SENSE 0x4d -#define SCSI_CD_MODE_SELECT_6 0x15 -#define SCSI_CD_MODE_SELECT_10 0x55 -#define SCSI_CD_MODE_SENSE_6 0x1a -#define SCSI_CD_MODE_SENSE_10 0x5a -#define SCSI_CD_PAUSE_RESUME 0x4b -#define SCSI_CD_PLAY_AUDIO_10 0x45 -#define SCSI_CD_PLAY_AUDIO_12 0xa5 -#define SCSI_CD_PLAY_AUDIO_MSF 0x47 -#define SCSI_CD_PLAY_AUDIO_TRACK_INDEX 0x48 -#define SCSI_CD_PLAY_TRACK_RELATIVE_10 0x49 -#define SCSI_CD_PLAY_TRACK_RELATIVE_12 0xa9 -#define SCSI_CD_PRE_FETCH 0x34 -#define SCSI_CD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e -#define SCSI_CD_READ_6 0x08 -#define SCSI_CD_READ_10 0x28 -#define SCSI_CD_READ_12 0xa8 -#define SCSI_CD_READ_BUFFER 0x3c -#define SCSI_CD_READ_CD_ROM_CAPACITY 0x25 -#define SCSI_CD_READ_HEADER 0x44 -#define SCSI_CD_READ_LONG 0x3e -#define SCSI_CD_READ_SUB_CHANNEL 0x42 -#define SCSI_CD_READ_TOC 0x43 -#define SCSI_CD_RECEIVE_DIAGNOSTIC_RESULT 0x1c -#define SCSI_CD_RELEASE 0x17 -#define SCSI_CD_REQUEST_SENSE 0x03 -#define SCSI_CD_RESERVE 0x16 -#define SCSI_CD_REZERO_UNIT 0x01 -#define SCSI_CD_SEARCH_DATA_EQUAL_10 0x31 -#define SCSI_CD_SEARCH_DATA_EQUAL_12 0xb1 -#define SCSI_CD_SEARCH_DATA_HIGH_10 0x30 -#define SCSI_CD_SEARCH_DATA_HIGH_12 0xb0 -#define SCSI_CD_SEARCH_DATA_LOW_10 0x32 -#define SCSI_CD_SEARCH_DATA_LOW_12 0xb2 -#define SCSI_CD_SEEK_6 0x0b -#define SCSI_CD_SEEK_10 0x2b -#define SCSI_CD_SEND_DIAGNOSTIC 0x1d -#define SCSI_CD_SET_LIMITS_10 0x33 -#define SCSI_CD_SET_LIMITS_12 0xb3 -#define SCSI_CD_START_STOP_UNIT 0x1b -#define SCSI_CD_SYNCHRONIZE_CACHE 0x35 -#define SCSI_CD_TEST_UNIT_READY 0x00 -#define SCSI_CD_VERIFY_10 0x2f -#define SCSI_CD_VERIFY_12 0xaf -#define SCSI_CD_WRITE_BUFFER 0x3b - - -/* Scanner devices */ - -#define SCSI_SC_CHANGE_DEFINITION 0x40 -#define SCSI_SC_COMPARE 0x39 -#define SCSI_SC_COPY 0x18 -#define SCSI_SC_COPY_AND_VERIFY 0x3a -#define SCSI_SC_GET_DATA_BUFFER_STATUS 0x34 -#define SCSI_SC_GET_WINDOW 0x25 -#define SCSI_SC_INQUIRY 0x12 -#define SCSI_SC_LOG_SELECT 0x4c -#define SCSI_SC_LOG_SENSE 0x4d -#define SCSI_SC_MODE_SELECT_6 0x15 -#define SCSI_SC_MODE_SELECT_10 0x55 -#define SCSI_SC_MODE_SENSE_6 0x1a -#define SCSI_SC_MODE_SENSE_10 0x5a -#define SCSI_SC_OBJECT_POSITION 0x31 -#define SCSI_SC_READ 0x28 -#define SCSI_SC_READ_BUFFER 0x3c -#define SCSI_SC_RECEIVE_DIAGNOSTIC_RESULTS 0x1c -#define SCSI_SC_RELEASE_UNIT 0x17 -#define SCSI_SC_REQUEST_SENSE 0x03 -#define SCSI_SC_RESERVE_UNIT 0x16 -#define SCSI_SC_SCAN 0x1b -#define SCSI_SC_SET_WINDOW 0x24 -#define SCSI_SC_SEND 0x2a -#define SCSI_SC_SEND_DIAGNOSTIC 0x1d -#define SCSI_SC_TEST_UNIT_READY 0x00 -#define SCSI_SC_WRITE_BUFFER 0x3b - - -/* Optical memory devices */ - -#define SCSI_OM_CHANGE_DEFINITION 0x40 -#define SCSI_OM_COMPARE 0x39 -#define SCSI_OM_COPY 0x18 -#define SCSI_OM_COPY_AND_VERIFY 0x3a -#define SCSI_OM_ERASE_10 0x2c -#define SCSI_OM_ERASE_12 0xac -#define SCSI_OM_FORMAT_UNIT 0x04 -#define SCSI_OM_INQUIRY 0x12 -#define SCSI_OM_LOCK_UNLOCK_CACHE 0x36 -#define SCSI_OM_LOG_SELECT 0x4c -#define SCSI_OM_LOG_SENSE 0x4d -#define SCSI_OM_MEDIUM_SCAN 0x38 -#define SCSI_OM_MODE_SELECT_6 0x15 -#define SCSI_OM_MODE_SELECT_10 0x55 -#define SCSI_OM_MODE_SENSE_6 0x1a -#define SCSI_OM_MODE_SENSE_10 0x5a -#define SCSI_OM_PRE_FETCH 0x34 -#define SCSI_OM_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e -#define SCSI_OM_READ_6 0x08 -#define SCSI_OM_READ_10 0x28 -#define SCSI_OM_READ_12 0xa8 -#define SCSI_OM_READ_BUFFER 0x3c -#define SCSI_OM_READ_CAPACITY 0x25 -#define SCSI_OM_READ_DEFECT_DATA_10 0x37 -#define SCSI_OM_READ_DEFECT_DATA_12 0xb7 -#define SCSI_OM_READ_GENERATION 0x29 -#define SCSI_OM_READ_LONG 0x3e -#define SCSI_OM_READ_UPDATED_BLOCK 0x2d -#define SCSI_OM_REASSIGN_BLOCKS 0x07 -#define SCSI_OM_RECEIVE_DIAGNOSTIC_RESULTS 0x1c -#define SCSI_OM_RELEASE 0x17 -#define SCSI_OM_REQUEST_SENSE 0x03 -#define SCSI_OM_RESERVE 0x16 -#define SCSI_OM_REZERO_UNIT 0x01 -#define SCSI_OM_SEARCH_DATA_EQUAL_10 0x31 -#define SCSI_OM_SEARCH_DATA_EQUAL_12 0xb1 -#define SCSI_OM_SEARCH_DATA_HIGH_10 0x30 -#define SCSI_OM_SEARCH_DATA_HIGH_12 0xb0 -#define SCSI_OM_SEARCH_DATA_LOW_10 0x32 -#define SCSI_OM_SEARCH_DATA_LOW_12 0xb2 -#define SCSI_OM_SEEK_6 0x0b -#define SCSI_OM_SEEK_10 0x2b -#define SCSI_OM_SEND_DIAGNOSTIC 0x1d -#define SCSI_OM_SET_LIMITS_10 0x33 -#define SCSI_OM_SET_LIMITS_12 0xb3 -#define SCSI_OM_START_STOP_UNIT 0x1b -#define SCSI_OM_SYNCHRONIZE_CACHE 0x35 -#define SCSI_OM_TEST_UNIT_READY 0x00 -#define SCSI_OM_UPDATE_BLOCK 0x3d -#define SCSI_OM_VERIFY_10 0x2f -#define SCSI_OM_VERIFY_12 0xaf -#define SCSI_OM_WRITE_6 0x0a -#define SCSI_OM_WRITE_10 0x2a -#define SCSI_OM_WRITE_12 0xaa -#define SCSI_OM_WRITE_AND_VERIFY_10 0x2e -#define SCSI_OM_WRITE_AND_VERIFY_12 0xae -#define SCSI_OM_WRITE_BUFFER 0x3b -#define SCSI_OM_WRITE_LONG 0x3f - - -/* Medium changer devices */ - -#define SCSI_MC_CHANGE_DEFINITION 0x40 -#define SCSI_MC_EXCHANGE_MEDIUM 0xa6 -#define SCSI_MC_INITIALIZE_ELEMENT_STATUS 0x07 -#define SCSI_MC_INQUIRY 0x12 -#define SCSI_MC_LOG_SELECT 0x4c -#define SCSI_MC_LOG_SENSE 0x4d -#define SCSI_MC_MODE_SELECT_6 0x15 -#define SCSI_MC_MODE_SELECT_10 0x55 -#define SCSI_MC_MODE_SENSE_6 0x1a -#define SCSI_MC_MODE_SENSE_10 0x5a -#define SCSI_MC_MOVE_MEDIUM 0xa5 -#define SCSI_MC_POSITION_TO_ELEMENT 0x2b -#define SCSI_MC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e -#define SCSI_MC_READ_BUFFER 0x3c -#define SCSI_MC_READ_ELEMENT_STATUS 0xb8 -#define SCSI_MC_RECEIVE_DIAGNOSTIC_RESULTS 0x1c -#define SCSI_MC_RELEASE 0x17 -#define SCSI_MC_REQUEST_VOLUME_ELEMENT_ADDRESS 0xb5 -#define SCSI_MC_REQUEST_SENSE 0x03 -#define SCSI_MC_RESERVE 0x16 -#define SCSI_MC_REZERO_UNIT 0x01 -#define SCSI_MC_SEND_DIAGNOSTIC 0x1d -#define SCSI_MC_SEND_VOLUME_TAG 0xb6 -#define SCSI_MC_TEST_UNIT_READY 0x00 -#define SCSI_MC_WRITE_BUFFER 0x3b - - -/* Communications devices */ - -#define SCSI_COM_CHANGE_DEFINITION 0x40 -#define SCSI_COM_GET_MESSAGE_6 0x08 -#define SCSI_COM_GET_MESSAGE_10 0x28 -#define SCSI_COM_GET_MESSAGE_12 0xa8 -#define SCSI_COM_INQUIRY 0x12 -#define SCSI_COM_LOG_SELECT 0x4c -#define SCSI_COM_LOG_SENSE 0x4d -#define SCSI_COM_MODE_SELECT_6 0x15 -#define SCSI_COM_MODE_SELECT_10 0x55 -#define SCSI_COM_MODE_SENSE_6 0x1a -#define SCSI_COM_MODE_SENSE_10 0x5a -#define SCSI_COM_READ_BUFFER 0x3c -#define SCSI_COM_RECEIVE_DIAGNOSTIC_RESULTS 0x1c -#define SCSI_COM_REQUEST_SENSE 0x03 -#define SCSI_COM_SEND_DIAGNOSTIC 0x1d -#define SCSI_COM_SEND_MESSAGE_6 0x0a -#define SCSI_COM_SEND_MESSAGE_10 0x2a -#define SCSI_COM_SEND_MESSAGE_12 0xaa -#define SCSI_COM_TEST_UNIT_READY 0x00 -#define SCSI_COM_WRITE_BUFFER 0x3b - diff --git a/tools/ioemu/iodev/scsidefs.h b/tools/ioemu/iodev/scsidefs.h deleted file mode 100644 index 86239e8a7d..0000000000 --- a/tools/ioemu/iodev/scsidefs.h +++ /dev/null @@ -1,286 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: scsidefs.h,v 1.4 2002/09/16 16:58:36 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// -// iodev/scsidefs.h -// $Id: scsidefs.h,v 1.4 2002/09/16 16:58:36 bdenney Exp $ -// -// This file was copied from ... ? -// - -//*************************************************************************** -// -// Name: SCSIDEFS.H -// -// Description: SCSI definitions ('C' Language) -// -//*************************************************************************** - -//*************************************************************************** -// %%% TARGET STATUS VALUES %%% -//*************************************************************************** -#define STATUS_GOOD 0x00 // Status Good -#define STATUS_CHKCOND 0x02 // Check Condition -#define STATUS_CONDMET 0x04 // Condition Met -#define STATUS_BUSY 0x08 // Busy -#define STATUS_INTERM 0x10 // Intermediate -#define STATUS_INTCDMET 0x14 // Intermediate-condition met -#define STATUS_RESCONF 0x18 // Reservation conflict -#define STATUS_COMTERM 0x22 // Command Terminated -#define STATUS_QFULL 0x28 // Queue full - -//*************************************************************************** -// %%% SCSI MISCELLANEOUS EQUATES %%% -//*************************************************************************** -#define MAXLUN 7 // Maximum Logical Unit Id -#define MAXTARG 7 // Maximum Target Id -#define MAX_SCSI_LUNS 64 // Maximum Number of SCSI LUNs -#define MAX_NUM_HA 8 // Maximum Number of SCSI HA's - -//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ -// -// %%% SCSI COMMAND OPCODES %%% -// -///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ - -//*************************************************************************** -// %%% Commands for all Device Types %%% -//*************************************************************************** -#define SCSI_CHANGE_DEF 0x40 // Change Definition (Optional) -#define SCSI_COMPARE 0x39 // Compare (O) -#define SCSI_COPY 0x18 // Copy (O) -#define SCSI_COP_VERIFY 0x3A // Copy and Verify (O) -#define SCSI_INQUIRY 0x12 // Inquiry (MANDATORY) -#define SCSI_LOG_SELECT 0x4C // Log Select (O) -#define SCSI_LOG_SENSE 0x4D // Log Sense (O) -#define SCSI_MODE_SEL6 0x15 // Mode Select 6-byte (Device Specific) -#define SCSI_MODE_SEL10 0x55 // Mode Select 10-byte (Device Specific) -#define SCSI_MODE_SEN6 0x1A // Mode Sense 6-byte (Device Specific) -#define SCSI_MODE_SEN10 0x5A // Mode Sense 10-byte (Device Specific) -#define SCSI_READ_BUFF 0x3C // Read Buffer (O) -#define SCSI_REQ_SENSE 0x03 // Request Sense (MANDATORY) -#define SCSI_SEND_DIAG 0x1D // Send Diagnostic (O) -#define SCSI_TST_U_RDY 0x00 // Test Unit Ready (MANDATORY) -#define SCSI_WRITE_BUFF 0x3B // Write Buffer (O) - -//*************************************************************************** -// %%% Commands Unique to Direct Access Devices %%% -//*************************************************************************** -#define SCSI_COMPARE 0x39 // Compare (O) -#define SCSI_FORMAT 0x04 // Format Unit (MANDATORY) -#define SCSI_LCK_UN_CAC 0x36 // Lock Unlock Cache (O) -#define SCSI_PREFETCH 0x34 // Prefetch (O) -#define SCSI_MED_REMOVL 0x1E // Prevent/Allow medium Removal (O) -#define SCSI_READ6 0x08 // Read 6-byte (MANDATORY) -#define SCSI_READ10 0x28 // Read 10-byte (MANDATORY) -#define SCSI_RD_CAPAC 0x25 // Read Capacity (MANDATORY) -#define SCSI_RD_DEFECT 0x37 // Read Defect Data (O) -#define SCSI_READ_LONG 0x3E // Read Long (O) -#define SCSI_REASS_BLK 0x07 // Reassign Blocks (O) -#define SCSI_RCV_DIAG 0x1C // Receive Diagnostic Results (O) -#define SCSI_RELEASE 0x17 // Release Unit (MANDATORY) -#define SCSI_REZERO 0x01 // Rezero Unit (O) -#define SCSI_SRCH_DAT_E 0x31 // Search Data Equal (O) -#define SCSI_SRCH_DAT_H 0x30 // Search Data High (O) -#define SCSI_SRCH_DAT_L 0x32 // Search Data Low (O) -#define SCSI_SEEK6 0x0B // Seek 6-Byte (O) -#define SCSI_SEEK10 0x2B // Seek 10-Byte (O) -#define SCSI_SEND_DIAG 0x1D // Send Diagnostics (MANDATORY) -#define SCSI_SET_LIMIT 0x33 // Set Limits (O) -#define SCSI_START_STP 0x1B // Start/Stop Unit (O) -#define SCSI_SYNC_CACHE 0x35 // Synchronize Cache (O) -#define SCSI_VERIFY 0x2F // Verify (O) -#define SCSI_WRITE6 0x0A // Write 6-Byte (MANDATORY) -#define SCSI_WRITE10 0x2A // Write 10-Byte (MANDATORY) -#define SCSI_WRT_VERIFY 0x2E // Write and Verify (O) -#define SCSI_WRITE_LONG 0x3F // Write Long (O) -#define SCSI_WRITE_SAME 0x41 // Write Same (O) - -//*************************************************************************** -// %%% Commands Unique to Sequential Access Devices %%% -//*************************************************************************** -#define SCSI_ERASE 0x19 // Erase (MANDATORY) -#define SCSI_LOAD_UN 0x1B // Load/Unload (O) -#define SCSI_LOCATE 0x2B // Locate (O) -#define SCSI_RD_BLK_LIM 0x05 // Read Block Limits (MANDATORY) -#define SCSI_READ_POS 0x34 // Read Position (O) -#define SCSI_READ_REV 0x0F // Read Reverse (O) -#define SCSI_REC_BF_DAT 0x14 // Recover Buffer Data (O) -#define SCSI_RESERVE 0x16 // Reserve Unit (MANDATORY) -#define SCSI_REWIND 0x01 // Rewind (MANDATORY) -#define SCSI_SPACE 0x11 // Space (MANDATORY) -#define SCSI_VERIFY_T 0x13 // Verify (Tape) (O) -#define SCSI_WRT_FILE 0x10 // Write Filemarks (MANDATORY) - -//*************************************************************************** -// %%% Commands Unique to Printer Devices %%% -//*************************************************************************** -#define SCSI_PRINT 0x0A // Print (MANDATORY) -#define SCSI_SLEW_PNT 0x0B // Slew and Print (O) -#define SCSI_STOP_PNT 0x1B // Stop Print (O) -#define SCSI_SYNC_BUFF 0x10 // Synchronize Buffer (O) - -//*************************************************************************** -// %%% Commands Unique to Processor Devices %%% -//*************************************************************************** -#define SCSI_RECEIVE 0x08 // Receive (O) -#define SCSI_SEND 0x0A // Send (O) - -//*************************************************************************** -// %%% Commands Unique to Write-Once Devices %%% -//*************************************************************************** -#define SCSI_MEDIUM_SCN 0x38 // Medium Scan (O) -#define SCSI_SRCHDATE10 0x31 // Search Data Equal 10-Byte (O) -#define SCSI_SRCHDATE12 0xB1 // Search Data Equal 12-Byte (O) -#define SCSI_SRCHDATH10 0x30 // Search Data High 10-Byte (O) -#define SCSI_SRCHDATH12 0xB0 // Search Data High 12-Byte (O) -#define SCSI_SRCHDATL10 0x32 // Search Data Low 10-Byte (O) -#define SCSI_SRCHDATL12 0xB2 // Search Data Low 12-Byte (O) -#define SCSI_SET_LIM_10 0x33 // Set Limits 10-Byte (O) -#define SCSI_SET_LIM_12 0xB3 // Set Limits 10-Byte (O) -#define SCSI_VERIFY10 0x2F // Verify 10-Byte (O) -#define SCSI_VERIFY12 0xAF // Verify 12-Byte (O) -#define SCSI_WRITE12 0xAA // Write 12-Byte (O) -#define SCSI_WRT_VER10 0x2E // Write and Verify 10-Byte (O) -#define SCSI_WRT_VER12 0xAE // Write and Verify 12-Byte (O) - -//*************************************************************************** -// %%% Commands Unique to CD-ROM Devices %%% -//*************************************************************************** -#define SCSI_PLAYAUD_10 0x45 // Play Audio 10-Byte (O) -#define SCSI_PLAYAUD_12 0xA5 // Play Audio 12-Byte 12-Byte (O) -#define SCSI_PLAYAUDMSF 0x47 // Play Audio MSF (O) -#define SCSI_PLAYA_TKIN 0x48 // Play Audio Track/Index (O) -#define SCSI_PLYTKREL10 0x49 // Play Track Relative 10-Byte (O) -#define SCSI_PLYTKREL12 0xA9 // Play Track Relative 12-Byte (O) -#define SCSI_READCDCAP 0x25 // Read CD-ROM Capacity (MANDATORY) -#define SCSI_READHEADER 0x44 // Read Header (O) -#define SCSI_SUBCHANNEL 0x42 // Read Subchannel (O) -#define SCSI_READ_TOC 0x43 // Read TOC (O) - -//*************************************************************************** -// %%% Commands Unique to Scanner Devices %%% -//*************************************************************************** -#define SCSI_GETDBSTAT 0x34 // Get Data Buffer Status (O) -#define SCSI_GETWINDOW 0x25 // Get Window (O) -#define SCSI_OBJECTPOS 0x31 // Object Postion (O) -#define SCSI_SCAN 0x1B // Scan (O) -#define SCSI_SETWINDOW 0x24 // Set Window (MANDATORY) - -//*************************************************************************** -// %%% Commands Unique to Optical Memory Devices %%% -//*************************************************************************** -#define SCSI_UpdateBlk 0x3D // Update Block (O) - -//*************************************************************************** -// %%% Commands Unique to Medium Changer Devices %%% -//*************************************************************************** -#define SCSI_EXCHMEDIUM 0xA6 // Exchange Medium (O) -#define SCSI_INITELSTAT 0x07 // Initialize Element Status (O) -#define SCSI_POSTOELEM 0x2B // Position to Element (O) -#define SCSI_REQ_VE_ADD 0xB5 // Request Volume Element Address (O) -#define SCSI_SENDVOLTAG 0xB6 // Send Volume Tag (O) - -//*************************************************************************** -// %%% Commands Unique to Communication Devices %%% -//*************************************************************************** -#define SCSI_GET_MSG_6 0x08 // Get Message 6-Byte (MANDATORY) -#define SCSI_GET_MSG_10 0x28 // Get Message 10-Byte (O) -#define SCSI_GET_MSG_12 0xA8 // Get Message 12-Byte (O) -#define SCSI_SND_MSG_6 0x0A // Send Message 6-Byte (MANDATORY) -#define SCSI_SND_MSG_10 0x2A // Send Message 10-Byte (O) -#define SCSI_SND_MSG_12 0xAA // Send Message 12-Byte (O) - -//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ -// -// %%% END OF SCSI COMMAND OPCODES %%% -// -///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ - -//*************************************************************************** -// %%% Request Sense Data Format %%% -//*************************************************************************** -typedef struct { - - BYTE ErrorCode; // Error Code (70H or 71H) - BYTE SegmentNum; // Number of current segment descriptor - BYTE SenseKey; // Sense Key(See bit definitions too) - BYTE InfoByte0; // Information MSB - BYTE InfoByte1; // Information MID - BYTE InfoByte2; // Information MID - BYTE InfoByte3; // Information LSB - BYTE AddSenLen; // Additional Sense Length - BYTE ComSpecInf0; // Command Specific Information MSB - BYTE ComSpecInf1; // Command Specific Information MID - BYTE ComSpecInf2; // Command Specific Information MID - BYTE ComSpecInf3; // Command Specific Information LSB - BYTE AddSenseCode; // Additional Sense Code - BYTE AddSenQual; // Additional Sense Code Qualifier - BYTE FieldRepUCode; // Field Replaceable Unit Code - BYTE SenKeySpec15; // Sense Key Specific 15th byte - BYTE SenKeySpec16; // Sense Key Specific 16th byte - BYTE SenKeySpec17; // Sense Key Specific 17th byte - BYTE AddSenseBytes; // Additional Sense Bytes - -} SENSE_DATA_FMT; - -//*************************************************************************** -// %%% REQUEST SENSE ERROR CODE %%% -//*************************************************************************** -#define SERROR_CURRENT 0x70 // Current Errors -#define SERROR_DEFERED 0x71 // Deferred Errors - -//*************************************************************************** -// %%% REQUEST SENSE BIT DEFINITIONS %%% -//*************************************************************************** -#define SENSE_VALID 0x80 // Byte 0 Bit 7 -#define SENSE_FILEMRK 0x80 // Byte 2 Bit 7 -#define SENSE_EOM 0x40 // Byte 2 Bit 6 -#define SENSE_ILI 0x20 // Byte 2 Bit 5 - -//*************************************************************************** -// %%% REQUEST SENSE SENSE KEY DEFINITIONS %%% -//*************************************************************************** -#define KEY_NOSENSE 0x00 // No Sense -#define KEY_RECERROR 0x01 // Recovered Error -#define KEY_NOTREADY 0x02 // Not Ready -#define KEY_MEDIUMERR 0x03 // Medium Error -#define KEY_HARDERROR 0x04 // Hardware Error -#define KEY_ILLGLREQ 0x05 // Illegal Request -#define KEY_UNITATT 0x06 // Unit Attention -#define KEY_DATAPROT 0x07 // Data Protect -#define KEY_BLANKCHK 0x08 // Blank Check -#define KEY_VENDSPEC 0x09 // Vendor Specific -#define KEY_COPYABORT 0x0A // Copy Abort -#define KEY_EQUAL 0x0C // Equal (Search) -#define KEY_VOLOVRFLW 0x0D // Volume Overflow -#define KEY_MISCOMP 0x0E // Miscompare (Search) -#define KEY_RESERVED 0x0F // Reserved - -//*************************************************************************** -// %%% PERIPHERAL DEVICE TYPE DEFINITIONS %%% -//*************************************************************************** -#define DTYPE_DASD 0x00 // Disk Device -#define DTYPE_SEQD 0x01 // Tape Device -#define DTYPE_PRNT 0x02 // Printer -#define DTYPE_PROC 0x03 // Processor -#define DTYPE_WORM 0x04 // Write-once read-multiple -#define DTYPE_CROM 0x05 // CD-ROM device -#define DTYPE_CDROM 0x05 // CD-ROM device -#define DTYPE_SCAN 0x06 // Scanner device -#define DTYPE_OPTI 0x07 // Optical memory device -#define DTYPE_JUKE 0x08 // Medium Changer device -#define DTYPE_COMM 0x09 // Communications device -#define DTYPE_RESL 0x0A // Reserved (low) -#define DTYPE_RESH 0x1E // Reserved (high) -#define DTYPE_UNKNOWN 0x1F // Unknown or no device type - -//*************************************************************************** -// %%% ANSI APPROVED VERSION DEFINITIONS %%% -//*************************************************************************** -#define ANSI_MAYBE 0x0 // Device may or may not be ANSI approved stand -#define ANSI_SCSI1 0x1 // Device complies to ANSI X3.131-1986 (SCSI-1) -#define ANSI_SCSI2 0x2 // Device complies to SCSI-2 -#define ANSI_RESLO 0x3 // Reserved (low) -#define ANSI_RESHI 0x7 // Reserved (high) diff --git a/tools/ioemu/iodev/scsipt.h b/tools/ioemu/iodev/scsipt.h deleted file mode 100644 index b3c8508abf..0000000000 --- a/tools/ioemu/iodev/scsipt.h +++ /dev/null @@ -1,144 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: scsipt.h,v 1.4 2002/09/16 16:58:36 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// -// iodev/scsipt.h -// $Id: scsipt.h,v 1.4 2002/09/16 16:58:36 bdenney Exp $ -// -// This file was copied from ... ? -// -// distilled information from various header files from Microsoft's -// DDK for Windows NT 4.0 -// - -#ifndef _SCSIPT_H_INC -#define _SCSIPT_H_INC - -#include - -typedef struct { - USHORT Length; - UCHAR ScsiStatus; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - UCHAR CdbLength; - UCHAR SenseInfoLength; - UCHAR DataIn; - ULONG DataTransferLength; - ULONG TimeOutValue; - ULONG DataBufferOffset; - ULONG SenseInfoOffset; - UCHAR Cdb[16]; -} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH; - - -typedef struct { - USHORT Length; - UCHAR ScsiStatus; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - UCHAR CdbLength; - UCHAR SenseInfoLength; - UCHAR DataIn; - ULONG DataTransferLength; - ULONG TimeOutValue; - PVOID DataBuffer; - ULONG SenseInfoOffset; - UCHAR Cdb[16]; -} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT; - - -typedef struct { - SCSI_PASS_THROUGH spt; - ULONG Filler; - UCHAR ucSenseBuf[32]; - UCHAR ucDataBuf[512]; -} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS; - - -typedef struct { - SCSI_PASS_THROUGH_DIRECT spt; - ULONG Filler; - UCHAR ucSenseBuf[32]; -} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER; - - - -typedef struct { - UCHAR NumberOfLogicalUnits; - UCHAR InitiatorBusId; - ULONG InquiryDataOffset; -} SCSI_BUS_DATA, *PSCSI_BUS_DATA; - - -typedef struct { - UCHAR NumberOfBusses; - SCSI_BUS_DATA BusData[1]; -} SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; - - -typedef struct { - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - BOOLEAN DeviceClaimed; - ULONG InquiryDataLength; - ULONG NextInquiryDataOffset; - UCHAR InquiryData[1]; -} SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; - - -typedef struct { - ULONG Length; - UCHAR PortNumber; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; -} SCSI_ADDRESS, *PSCSI_ADDRESS; - - -/* - * method codes - */ -#define METHOD_BUFFERED 0 -#define METHOD_IN_DIRECT 1 -#define METHOD_OUT_DIRECT 2 -#define METHOD_NEITHER 3 - -/* - * file access values - */ -#define FILE_ANY_ACCESS 0 -#define FILE_READ_ACCESS (0x0001) -#define FILE_WRITE_ACCESS (0x0002) - - -#define IOCTL_SCSI_BASE 0x00000004 - -/* - * constants for DataIn member of SCSI_PASS_THROUGH* structures - */ -#define SCSI_IOCTL_DATA_OUT 0 -#define SCSI_IOCTL_DATA_IN 1 -#define SCSI_IOCTL_DATA_UNSPECIFIED 2 - -/* - * Standard IOCTL define - */ -#define CTL_CODE( DevType, Function, Method, Access ) ( \ - ((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \ -) - -#define IOCTL_SCSI_PASS_THROUGH CTL_CODE( IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) -#define IOCTL_SCSI_MINIPORT CTL_CODE( IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) -#define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE( IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE( IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS) -#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE( IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS ) -#define IOCTL_SCSI_GET_ADDRESS CTL_CODE( IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS ) - - - -#endif diff --git a/tools/ioemu/iodev/serial.cc b/tools/ioemu/iodev/serial.cc deleted file mode 100644 index 02deec3014..0000000000 --- a/tools/ioemu/iodev/serial.cc +++ /dev/null @@ -1,1001 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: serial.cc,v 1.41 2003/11/09 00:14:43 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -// Peter Grehan (grehan@iprg.nokia.com) coded the original version of this -// serial emulation. He implemented a single 8250, and allow terminal -// input/output to stdout on FreeBSD. -// The current version emulates a single 16550A with FIFO. Terminal -// input/output now works on some more platforms. - - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" - -#define LOG_THIS theSerialDevice-> - -#if USE_RAW_SERIAL -#include -#endif - -#ifdef WIN32 -#ifndef __MINGW32__ -// +++ -//#include -#include -#endif -#endif - -#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__linux__) || defined(__GNU__) || defined(__APPLE__) -#define SERIAL_ENABLE -#endif - -#ifdef SERIAL_ENABLE -extern "C" { -#include -}; -#endif - -#ifdef SERIAL_ENABLE -static struct termios term_orig, term_new; -#endif - -static int tty_id; - -bx_serial_c *theSerialDevice = NULL; - - int -libserial_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - theSerialDevice = new bx_serial_c (); - bx_devices.pluginSerialDevice = theSerialDevice; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theSerialDevice, BX_PLUGIN_SERIAL); - return(0); // Success -} - - void -libserial_LTX_plugin_fini(void) -{ -} - -bx_serial_c::bx_serial_c(void) -{ - put("SER"); - settype(SERLOG); - tty_id = -1; - for (int i=0; iget ()) && (tty_id >= 0)) - tcsetattr(tty_id, TCSAFLUSH, &term_orig); -#endif - // nothing for now -} - - - void -bx_serial_c::init(void) -{ - Bit16u ports[BX_SERIAL_MAXDEV] = {0x03f8, 0x02f8, 0x03e8, 0x02e8}; - char name[16]; - - if (!bx_options.com[0].Oenabled->get ()) - return; - -#ifdef SERIAL_ENABLE - if (strlen(bx_options.com[0].Odev->getptr ()) > 0) { - tty_id = open(bx_options.com[0].Odev->getptr (), O_RDWR|O_NONBLOCK,600); - if (tty_id < 0) - BX_PANIC(("open of %s (%s) failed\n", - "com1", bx_options.com[0].Odev->getptr ())); - BX_DEBUG(("tty_id: %d",tty_id)); - tcgetattr(tty_id, &term_orig); - bcopy((caddr_t) &term_orig, (caddr_t) &term_new, sizeof(struct termios)); - cfmakeraw(&term_new); - term_new.c_oflag |= OPOST | ONLCR; // Enable NL to CR-NL translation -#ifndef TRUE_CTLC - // ctl-C will exit Bochs, or trap to the debugger - term_new.c_iflag &= ~IGNBRK; - term_new.c_iflag |= BRKINT; - term_new.c_lflag |= ISIG; -#else - // ctl-C will be delivered to the serial port - term_new.c_iflag |= IGNBRK; - term_new.c_iflag &= ~BRKINT; -#endif /* !def TRUE_CTLC */ - term_new.c_iflag = 0; - term_new.c_oflag = 0; - term_new.c_cflag = CS8|CREAD|CLOCAL; - term_new.c_lflag = 0; - term_new.c_cc[VMIN] = 1; - term_new.c_cc[VTIME] = 0; - //term_new.c_iflag |= IXOFF; - tcsetattr(tty_id, TCSAFLUSH, &term_new); - } -#endif /* def SERIAL_ENABLE */ - // nothing for now -#if USE_RAW_SERIAL - this->raw = new serial_raw("/dev/cua0", SIGUSR1); -#endif // USE_RAW_SERIAL - - /* - * Put the UART registers into their RESET state - */ - for (unsigned i=0; iget ()) { - sprintf(name, "Serial Port %d", i + 1); - /* serial interrupt */ - BX_SER_THIS s[i].IRQ = 4 - (i & 1); - if (i < 2) { - DEV_register_irq(BX_SER_THIS s[i].IRQ, name); - } - /* internal state */ - BX_SER_THIS s[i].ls_ipending = 0; - BX_SER_THIS s[i].ms_ipending = 0; - BX_SER_THIS s[i].rx_ipending = 0; - BX_SER_THIS s[i].fifo_ipending = 0; - BX_SER_THIS s[i].ls_interrupt = 0; - BX_SER_THIS s[i].ms_interrupt = 0; - BX_SER_THIS s[i].rx_interrupt = 0; - BX_SER_THIS s[i].tx_interrupt = 0; - BX_SER_THIS s[i].fifo_interrupt = 0; - - if (BX_SER_THIS s[i].tx_timer_index == BX_NULL_TIMER_HANDLE) { - BX_SER_THIS s[i].tx_timer_index = - bx_pc_system.register_timer(this, tx_timer_handler, 0, - 0,0, "serial.tx"); // one-shot, inactive - } - - if (BX_SER_THIS s[i].rx_timer_index == BX_NULL_TIMER_HANDLE) { - BX_SER_THIS s[i].rx_timer_index = - bx_pc_system.register_timer(this, rx_timer_handler, 0, - 0,0, "serial.rx"); // one-shot, inactive - } - if (BX_SER_THIS s[i].fifo_timer_index == BX_NULL_TIMER_HANDLE) { - BX_SER_THIS s[i].fifo_timer_index = - bx_pc_system.register_timer(this, fifo_timer_handler, 0, - 0,0, "serial.fifo"); // one-shot, inactive - } - BX_SER_THIS s[i].rx_pollstate = BX_SER_RXIDLE; - - /* int enable: b0000 0000 */ - BX_SER_THIS s[i].int_enable.rxdata_enable = 0; - BX_SER_THIS s[i].int_enable.txhold_enable = 0; - BX_SER_THIS s[i].int_enable.rxlstat_enable = 0; - BX_SER_THIS s[i].int_enable.modstat_enable = 0; - - /* int ID: b0000 0001 */ - BX_SER_THIS s[i].int_ident.ipending = 1; - BX_SER_THIS s[i].int_ident.int_ID = 0; - - /* FIFO control: b0000 0000 */ - BX_SER_THIS s[i].fifo_cntl.enable = 0; - BX_SER_THIS s[i].fifo_cntl.rxtrigger = 0; - BX_SER_THIS s[i].rx_fifo_end = 0; - BX_SER_THIS s[i].tx_fifo_end = 0; - - /* Line Control reg: b0000 0000 */ - BX_SER_THIS s[i].line_cntl.wordlen_sel = 0; - BX_SER_THIS s[i].line_cntl.stopbits = 0; - BX_SER_THIS s[i].line_cntl.parity_enable = 0; - BX_SER_THIS s[i].line_cntl.evenparity_sel = 0; - BX_SER_THIS s[i].line_cntl.stick_parity = 0; - BX_SER_THIS s[i].line_cntl.break_cntl = 0; - BX_SER_THIS s[i].line_cntl.dlab = 0; - - /* Modem Control reg: b0000 0000 */ - BX_SER_THIS s[i].modem_cntl.dtr = 0; - BX_SER_THIS s[i].modem_cntl.rts = 0; - BX_SER_THIS s[i].modem_cntl.out1 = 0; - BX_SER_THIS s[i].modem_cntl.out2 = 0; - BX_SER_THIS s[i].modem_cntl.local_loopback = 0; - - /* Line Status register: b0110 0000 */ - BX_SER_THIS s[i].line_status.rxdata_ready = 0; - BX_SER_THIS s[i].line_status.overrun_error = 0; - BX_SER_THIS s[i].line_status.parity_error = 0; - BX_SER_THIS s[i].line_status.framing_error = 0; - BX_SER_THIS s[i].line_status.break_int = 0; - BX_SER_THIS s[i].line_status.thr_empty = 1; - BX_SER_THIS s[i].line_status.tsr_empty = 1; - BX_SER_THIS s[i].line_status.fifo_error = 0; - - /* Modem Status register: bXXXX 0000 */ - BX_SER_THIS s[i].modem_status.delta_cts = 0; - BX_SER_THIS s[i].modem_status.delta_dsr = 0; - BX_SER_THIS s[i].modem_status.ri_trailedge = 0; - BX_SER_THIS s[i].modem_status.delta_dcd = 0; - BX_SER_THIS s[i].modem_status.cts = 0; - BX_SER_THIS s[i].modem_status.dsr = 0; - BX_SER_THIS s[i].modem_status.ri = 0; - BX_SER_THIS s[i].modem_status.dcd = 0; - - BX_SER_THIS s[i].scratch = 0; /* scratch register */ - BX_SER_THIS s[i].divisor_lsb = 1; /* divisor-lsb register */ - BX_SER_THIS s[i].divisor_msb = 0; /* divisor-msb register */ - - BX_SER_THIS s[i].baudrate = 115200; - - for (unsigned addr=ports[i]; addr<(unsigned)(ports[i]+8); addr++) { - BX_DEBUG(("register read/write: 0x%04x",addr)); - DEV_register_ioread_handler(this, read_handler, addr, name, 1); - DEV_register_iowrite_handler(this, write_handler, addr, name, 1); - } - BX_INFO(("com%d at 0x%04x irq %d", i+1, ports[i], BX_SER_THIS s[i].IRQ)); - } - } -} - - void -bx_serial_c::reset(unsigned type) -{ -} - - void -bx_serial_c::lower_interrupt(Bit8u port) -{ - /* If there are no more ints pending, clear the irq */ - if ((BX_SER_THIS s[port].rx_interrupt == 0) && - (BX_SER_THIS s[port].tx_interrupt == 0) && - (BX_SER_THIS s[port].ls_interrupt == 0) && - (BX_SER_THIS s[port].ms_interrupt == 0) && - (BX_SER_THIS s[port].fifo_interrupt == 0)) { - DEV_pic_lower_irq(BX_SER_THIS s[port].IRQ); - } -} - - void -bx_serial_c::raise_interrupt(Bit8u port, int type) -{ - bx_bool gen_int = 0; - - switch (type) { - case BX_SER_INT_IER: /* IER has changed */ - gen_int = 1; - break; - case BX_SER_INT_RXDATA: - if (BX_SER_THIS s[port].int_enable.rxdata_enable) { - BX_SER_THIS s[port].rx_interrupt = 1; - gen_int = 1; - } else { - BX_SER_THIS s[port].rx_ipending = 1; - } - break; - case BX_SER_INT_TXHOLD: - if (BX_SER_THIS s[port].int_enable.txhold_enable) { - BX_SER_THIS s[port].tx_interrupt = 1; - gen_int = 1; - } - break; - case BX_SER_INT_RXLSTAT: - if (BX_SER_THIS s[port].int_enable.rxlstat_enable) { - BX_SER_THIS s[port].ls_interrupt = 1; - gen_int = 1; - } else { - BX_SER_THIS s[port].ls_ipending = 1; - } - break; - case BX_SER_INT_MODSTAT: - if ((BX_SER_THIS s[port].ms_ipending == 1) && - (BX_SER_THIS s[port].int_enable.modstat_enable == 1)) { - BX_SER_THIS s[port].ms_interrupt = 1; - BX_SER_THIS s[port].ms_ipending = 0; - gen_int = 1; - } - break; - case BX_SER_INT_FIFO: - if (BX_SER_THIS s[port].int_enable.rxdata_enable) { - BX_SER_THIS s[port].fifo_interrupt = 1; - gen_int = 1; - } else { - BX_SER_THIS s[port].fifo_ipending = 1; - } - break; - } - if (gen_int && BX_SER_THIS s[port].modem_cntl.out2) { - DEV_pic_raise_irq(BX_SER_THIS s[port].IRQ); - } -} - - // static IO port read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_serial_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_SER_SMF - bx_serial_c *class_ptr = (bx_serial_c *) this_ptr; - - return( class_ptr->read(address, io_len) ); -} - - - Bit32u -bx_serial_c::read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_SER_SMF - //UNUSED(address); - Bit8u val; - - /* SERIAL PORT 1 */ - - BX_DEBUG(("register read from address 0x%04x - ", (unsigned) address)); - - switch (address) { - case 0x03F8: /* receive buffer, or divisor latch LSB if DLAB set */ - if (BX_SER_THIS s[0].line_cntl.dlab) { - val = BX_SER_THIS s[0].divisor_lsb; - } else { - if (BX_SER_THIS s[0].fifo_cntl.enable) { - val = BX_SER_THIS s[0].rx_fifo[0]; - if (BX_SER_THIS s[0].rx_fifo_end > 0) { - memcpy(&BX_SER_THIS s[0].rx_fifo[0], &BX_SER_THIS s[0].rx_fifo[1], 15); - BX_SER_THIS s[0].rx_fifo_end--; - } - if (BX_SER_THIS s[0].rx_fifo_end == 0) { - BX_SER_THIS s[0].line_status.rxdata_ready = 0; - BX_SER_THIS s[0].rx_interrupt = 0; - BX_SER_THIS s[0].rx_ipending = 0; - BX_SER_THIS s[0].fifo_interrupt = 0; - BX_SER_THIS s[0].fifo_ipending = 0; - lower_interrupt(0); - } - } else { - val = BX_SER_THIS s[0].rxbuffer; - BX_SER_THIS s[0].line_status.rxdata_ready = 0; - BX_SER_THIS s[0].rx_interrupt = 0; - BX_SER_THIS s[0].rx_ipending = 0; - lower_interrupt(0); - } - } - break; - - case 0x03F9: /* interrupt enable register, or div. latch MSB */ - if (BX_SER_THIS s[0].line_cntl.dlab) { - val = BX_SER_THIS s[0].divisor_msb; - } else { - val = BX_SER_THIS s[0].int_enable.rxdata_enable | - (BX_SER_THIS s[0].int_enable.txhold_enable << 1) | - (BX_SER_THIS s[0].int_enable.rxlstat_enable << 2) | - (BX_SER_THIS s[0].int_enable.modstat_enable << 3); - } - break; - - case 0x03FA: /* interrupt ID register */ - /* - * Set the interrupt ID based on interrupt source - */ - if (BX_SER_THIS s[0].ls_interrupt) { - BX_SER_THIS s[0].int_ident.int_ID = 0x3; - BX_SER_THIS s[0].int_ident.ipending = 0; - } else if (BX_SER_THIS s[0].fifo_interrupt) { - BX_SER_THIS s[0].int_ident.int_ID = 0x6; - BX_SER_THIS s[0].int_ident.ipending = 0; - } else if (BX_SER_THIS s[0].rx_interrupt) { - BX_SER_THIS s[0].int_ident.int_ID = 0x2; - BX_SER_THIS s[0].int_ident.ipending = 0; - } else if (BX_SER_THIS s[0].tx_interrupt) { - BX_SER_THIS s[0].int_ident.int_ID = 0x1; - BX_SER_THIS s[0].int_ident.ipending = 0; - } else if (BX_SER_THIS s[0].ms_interrupt) { - BX_SER_THIS s[0].int_ident.int_ID = 0x0; - BX_SER_THIS s[0].int_ident.ipending = 0; - } else { - BX_SER_THIS s[0].int_ident.int_ID = 0x0; - BX_SER_THIS s[0].int_ident.ipending = 1; - } - BX_SER_THIS s[0].tx_interrupt = 0; - lower_interrupt(0); - - val = BX_SER_THIS s[0].int_ident.ipending | - (BX_SER_THIS s[0].int_ident.int_ID << 1) | - (BX_SER_THIS s[0].fifo_cntl.enable ? 0xc0 : 0x00); - break; - - case 0x03FB: /* Line control register */ - val = BX_SER_THIS s[0].line_cntl.wordlen_sel | - (BX_SER_THIS s[0].line_cntl.stopbits << 2) | - (BX_SER_THIS s[0].line_cntl.parity_enable << 3) | - (BX_SER_THIS s[0].line_cntl.evenparity_sel << 4) | - (BX_SER_THIS s[0].line_cntl.stick_parity << 5) | - (BX_SER_THIS s[0].line_cntl.break_cntl << 6) | - (BX_SER_THIS s[0].line_cntl.dlab << 7); - break; - - case 0x03FC: /* MODEM control register */ - val = BX_SER_THIS s[0].modem_cntl.dtr | - (BX_SER_THIS s[0].modem_cntl.rts << 1) | - (BX_SER_THIS s[0].modem_cntl.out1 << 2) | - (BX_SER_THIS s[0].modem_cntl.out2 << 3) | - (BX_SER_THIS s[0].modem_cntl.local_loopback << 4); - break; - - case 0x03FD: /* Line status register */ - val = BX_SER_THIS s[0].line_status.rxdata_ready | - (BX_SER_THIS s[0].line_status.overrun_error << 1) | - (BX_SER_THIS s[0].line_status.parity_error << 2) | - (BX_SER_THIS s[0].line_status.framing_error << 3) | - (BX_SER_THIS s[0].line_status.break_int << 4) | - (BX_SER_THIS s[0].line_status.thr_empty << 5) | - (BX_SER_THIS s[0].line_status.tsr_empty << 6) | - (BX_SER_THIS s[0].line_status.fifo_error << 7); - BX_SER_THIS s[0].line_status.overrun_error = 0; - BX_SER_THIS s[0].line_status.break_int = 0; - BX_SER_THIS s[0].ls_interrupt = 0; - BX_SER_THIS s[0].ls_ipending = 0; - lower_interrupt(0); - break; - - case 0x03FE: /* MODEM status register */ - val = BX_SER_THIS s[0].modem_status.delta_cts | - (BX_SER_THIS s[0].modem_status.delta_dsr << 1) | - (BX_SER_THIS s[0].modem_status.ri_trailedge << 2) | - (BX_SER_THIS s[0].modem_status.delta_dcd << 3) | - (BX_SER_THIS s[0].modem_status.cts << 4) | - (BX_SER_THIS s[0].modem_status.dsr << 5) | - (BX_SER_THIS s[0].modem_status.ri << 6) | - (BX_SER_THIS s[0].modem_status.dcd << 7); - BX_SER_THIS s[0].modem_status.delta_cts = 0; - BX_SER_THIS s[0].modem_status.delta_dsr = 0; - BX_SER_THIS s[0].modem_status.ri_trailedge = 0; - BX_SER_THIS s[0].modem_status.delta_dcd = 0; - BX_SER_THIS s[0].ms_interrupt = 0; - BX_SER_THIS s[0].ms_ipending = 0; - lower_interrupt(0); - break; - - case 0x03FF: /* scratch register */ - val = BX_SER_THIS s[0].scratch; - break; - - default: - val = 0; // keep compiler happy - BX_PANIC(("unsupported io read from address=0x%04x!", - (unsigned) address)); - break; - } - - BX_DEBUG(("val = 0x%02x", (unsigned) val)); - - return(val); -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - -void -bx_serial_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_SER_SMF - bx_serial_c *class_ptr = (bx_serial_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - -void -bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_SER_SMF - bx_bool prev_cts, prev_dsr, prev_ri, prev_dcd; - bx_bool new_rx_ien, new_tx_ien, new_ls_ien, new_ms_ien; - bx_bool gen_int = 0; - - /* SERIAL PORT 1 */ - - BX_DEBUG(("write to address: 0x%04x = 0x%02x", - (unsigned) address, (unsigned) value)); - - switch (address) { - case 0x03F8: /* transmit buffer, or divisor latch LSB if DLAB set */ - if (BX_SER_THIS s[0].line_cntl.dlab) { - BX_SER_THIS s[0].divisor_lsb = value; - - if ((value != 0) || (BX_SER_THIS s[0].divisor_msb != 0)) { - BX_SER_THIS s[0].baudrate = (int) (BX_PC_CLOCK_XTL / - (16 * ((BX_SER_THIS s[0].divisor_msb << 8) | - BX_SER_THIS s[0].divisor_lsb))); -#if USE_RAW_SERIAL - BX_SER_THIS raw->set_baudrate(BX_SER_THIS s[0].baudrate); -#endif // USE_RAW_SERIAL - } - } else { - Bit8u bitmask = 0xff >> (3 - BX_SER_THIS s[0].line_cntl.wordlen_sel); - if (BX_SER_THIS s[0].line_status.thr_empty) { - if (BX_SER_THIS s[0].fifo_cntl.enable) { - BX_SER_THIS s[0].tx_fifo[BX_SER_THIS s[0].tx_fifo_end++] = value & bitmask; - } else { - BX_SER_THIS s[0].thrbuffer = value & bitmask; - } - BX_SER_THIS s[0].line_status.thr_empty = 0; - if (BX_SER_THIS s[0].line_status.tsr_empty) { - if (BX_SER_THIS s[0].fifo_cntl.enable) { - BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].tx_fifo[0]; - memcpy(&BX_SER_THIS s[0].tx_fifo[0], &BX_SER_THIS s[0].tx_fifo[1], 15); - BX_SER_THIS s[0].line_status.thr_empty = (--BX_SER_THIS s[0].tx_fifo_end == 0); - } else { - BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].thrbuffer; - BX_SER_THIS s[0].line_status.thr_empty = 1; - } - BX_SER_THIS s[0].line_status.tsr_empty = 0; - raise_interrupt(0, BX_SER_INT_TXHOLD); - bx_pc_system.activate_timer(BX_SER_THIS s[0].tx_timer_index, - (int) (1000000.0 / BX_SER_THIS s[0].baudrate * - (BX_SER_THIS s[0].line_cntl.wordlen_sel + 5)), - 0); /* not continuous */ - } else { - BX_SER_THIS s[0].tx_interrupt = 0; - lower_interrupt(0); - } - } else { - if (BX_SER_THIS s[0].fifo_cntl.enable) { - if (BX_SER_THIS s[0].tx_fifo_end < 16) { - BX_SER_THIS s[0].tx_fifo[BX_SER_THIS s[0].tx_fifo_end++] = value & bitmask; - } else { - BX_ERROR(("com1: transmit FIFO overflow")); - } - } else { - BX_ERROR(("write to tx hold register when not empty")); - } - } - } - break; - - case 0x03F9: /* interrupt enable register, or div. latch MSB */ - if (BX_SER_THIS s[0].line_cntl.dlab) { - BX_SER_THIS s[0].divisor_msb = value; - - if ((value != 0) || (BX_SER_THIS s[0].divisor_lsb != 0)) { - BX_SER_THIS s[0].baudrate = (int) (BX_PC_CLOCK_XTL / - (16 * ((BX_SER_THIS s[0].divisor_msb << 8) | - BX_SER_THIS s[0].divisor_lsb))); -#if USE_RAW_SERIAL - BX_SER_THIS raw->set_baudrate(BX_SER_THIS s[0].baudrate); -#endif // USE_RAW_SERIAL - } - } else { - new_rx_ien = value & 0x01; - new_tx_ien = (value & 0x02) >> 1; - new_ls_ien = (value & 0x04) >> 2; - new_ms_ien = (value & 0x08) >> 3; - if (new_ms_ien != BX_SER_THIS s[0].int_enable.modstat_enable) { - BX_SER_THIS s[0].int_enable.modstat_enable = new_ms_ien; - if (BX_SER_THIS s[0].int_enable.modstat_enable == 1) { - if (BX_SER_THIS s[0].ms_ipending == 1) { - BX_SER_THIS s[0].ms_interrupt = 1; - BX_SER_THIS s[0].ms_ipending = 0; - gen_int = 1; - } - } else { - if (BX_SER_THIS s[0].ms_interrupt == 1) { - BX_SER_THIS s[0].ms_interrupt = 0; - BX_SER_THIS s[0].ms_ipending = 1; - lower_interrupt(0); - } - } - } - if (new_tx_ien != BX_SER_THIS s[0].int_enable.txhold_enable) { - BX_SER_THIS s[0].int_enable.txhold_enable = new_tx_ien; - if (BX_SER_THIS s[0].int_enable.txhold_enable == 1) { - BX_SER_THIS s[0].tx_interrupt = BX_SER_THIS s[0].line_status.thr_empty; - if (BX_SER_THIS s[0].tx_interrupt) gen_int = 1; - } else { - BX_SER_THIS s[0].tx_interrupt = 0; - lower_interrupt(0); - } - } - if (new_rx_ien != BX_SER_THIS s[0].int_enable.rxdata_enable) { - BX_SER_THIS s[0].int_enable.rxdata_enable = new_rx_ien; - if (BX_SER_THIS s[0].int_enable.rxdata_enable == 1) { - if (BX_SER_THIS s[0].fifo_ipending == 1) { - BX_SER_THIS s[0].fifo_interrupt = 1; - BX_SER_THIS s[0].fifo_ipending = 0; - gen_int = 1; - } - if (BX_SER_THIS s[0].rx_ipending == 1) { - BX_SER_THIS s[0].rx_interrupt = 1; - BX_SER_THIS s[0].rx_ipending = 0; - gen_int = 1; - } - } else { - if (BX_SER_THIS s[0].rx_interrupt == 1) { - BX_SER_THIS s[0].rx_interrupt = 0; - BX_SER_THIS s[0].rx_ipending = 1; - lower_interrupt(0); - } - if (BX_SER_THIS s[0].fifo_interrupt == 1) { - BX_SER_THIS s[0].fifo_interrupt = 0; - BX_SER_THIS s[0].fifo_ipending = 1; - lower_interrupt(0); - } - } - } - if (new_ls_ien != BX_SER_THIS s[0].int_enable.rxlstat_enable) { - BX_SER_THIS s[0].int_enable.rxlstat_enable = new_ls_ien; - if (BX_SER_THIS s[0].int_enable.rxlstat_enable == 1) { - if (BX_SER_THIS s[0].ls_ipending == 1) { - BX_SER_THIS s[0].ls_interrupt = 1; - BX_SER_THIS s[0].ls_ipending = 0; - gen_int = 1; - } - } else { - if (BX_SER_THIS s[0].ls_interrupt == 1) { - BX_SER_THIS s[0].ls_interrupt = 0; - BX_SER_THIS s[0].ls_ipending = 1; - lower_interrupt(0); - } - } - } - if (gen_int) raise_interrupt(0, BX_SER_INT_IER); - } - break; - - case 0x03FA: /* FIFO control register */ - if (!BX_SER_THIS s[0].fifo_cntl.enable && (value & 0x01)) { - BX_INFO(("FIFO enabled")); - BX_SER_THIS s[0].rx_fifo_end = 0; - BX_SER_THIS s[0].tx_fifo_end = 0; - } - BX_SER_THIS s[0].fifo_cntl.enable = value & 0x01; - if (value & 0x02) { - BX_SER_THIS s[0].rx_fifo_end = 0; - } - if (value & 0x04) { - BX_SER_THIS s[0].tx_fifo_end = 0; - } - BX_SER_THIS s[0].fifo_cntl.rxtrigger = (value & 0xc0) >> 6; - break; - - case 0x03FB: /* Line control register */ -#if !USE_RAW_SERIAL - if ((value & 0x3) != 0x3) { - /* ignore this: this is set by FreeBSD when the console - code wants to set DLAB */ - } -#endif // !USE_RAW_SERIAL -#if USE_RAW_SERIAL - if (BX_SER_THIS s[0].line_cntl.wordlen_sel != (value & 0x3)) { - BX_SER_THIS raw->set_data_bits((value & 0x3) + 5); - } - if (BX_SER_THIS s[0].line_cntl.stopbits != (value & 0x4) >> 2) { - BX_SER_THIS raw->set_stop_bits((value & 0x4 >> 2) ? 2 : 1); - } - if (BX_SER_THIS s[0].line_cntl.parity_enable != (value & 0x8) >> 3 || - BX_SER_THIS s[0].line_cntl.evenparity_sel != (value & 0x10) >> 4 || - BX_SER_THIS s[0].line_cntl.stick_parity != (value & 0x20) >> 5) { - if (((value & 0x20) >> 5) && - ((value & 0x8) >> 3)) - BX_PANIC(("sticky parity set and parity enabled")); - BX_SER_THIS raw->set_parity_mode(((value & 0x8) >> 3), - ((value & 0x10) >> 4) ? P_EVEN : P_ODD); - } - if (BX_SER_THIS s[0].line_cntl.break_cntl && !((value & 0x40) >> 6)) { - BX_SER_THIS raw->transmit(C_BREAK); - } -#endif // USE_RAW_SERIAL - - BX_SER_THIS s[0].line_cntl.wordlen_sel = value & 0x3; - /* These are ignored, but set them up so they can be read back */ - BX_SER_THIS s[0].line_cntl.stopbits = (value & 0x4) >> 2; - BX_SER_THIS s[0].line_cntl.parity_enable = (value & 0x8) >> 3; - BX_SER_THIS s[0].line_cntl.evenparity_sel = (value & 0x10) >> 4; - BX_SER_THIS s[0].line_cntl.stick_parity = (value & 0x20) >> 5; - BX_SER_THIS s[0].line_cntl.break_cntl = (value & 0x40) >> 6; - /* used when doing future writes */ - if (BX_SER_THIS s[0].line_cntl.dlab && - !((value & 0x80) >> 7)) { - // Start the receive polling process if not already started - // and there is a valid baudrate. - if (BX_SER_THIS s[0].rx_pollstate == BX_SER_RXIDLE && - BX_SER_THIS s[0].baudrate != 0) { - BX_SER_THIS s[0].rx_pollstate = BX_SER_RXPOLL; - bx_pc_system.activate_timer(BX_SER_THIS s[0].rx_timer_index, - (int) (1000000.0 / BX_SER_THIS s[0].baudrate * - (BX_SER_THIS s[0].line_cntl.wordlen_sel + 5)), - 0); /* not continuous */ - } - BX_DEBUG(("baud rate set - %d", BX_SER_THIS s[0].baudrate)); - } - BX_SER_THIS s[0].line_cntl.dlab = (value & 0x80) >> 7; - break; - - case 0x03FC: /* MODEM control register */ - if ((value & 0x01) == 0) { -#if USE_RAW_SERIAL - BX_SER_THIS raw->send_hangup(); -#endif - } - - BX_SER_THIS s[0].modem_cntl.dtr = value & 0x01; - BX_SER_THIS s[0].modem_cntl.rts = (value & 0x02) >> 1; - BX_SER_THIS s[0].modem_cntl.out1 = (value & 0x04) >> 2; - BX_SER_THIS s[0].modem_cntl.out2 = (value & 0x08) >> 3; - BX_SER_THIS s[0].modem_cntl.local_loopback = (value & 0x10) >> 4; - - if (BX_SER_THIS s[0].modem_cntl.local_loopback) { - prev_cts = BX_SER_THIS s[0].modem_status.cts; - prev_dsr = BX_SER_THIS s[0].modem_status.dsr; - prev_ri = BX_SER_THIS s[0].modem_status.ri; - prev_dcd = BX_SER_THIS s[0].modem_status.dcd; - BX_SER_THIS s[0].modem_status.cts = BX_SER_THIS s[0].modem_cntl.rts; - BX_SER_THIS s[0].modem_status.dsr = BX_SER_THIS s[0].modem_cntl.dtr; - BX_SER_THIS s[0].modem_status.ri = BX_SER_THIS s[0].modem_cntl.out1; - BX_SER_THIS s[0].modem_status.dcd = BX_SER_THIS s[0].modem_cntl.out2; - if (BX_SER_THIS s[0].modem_status.cts != prev_cts) { - BX_SER_THIS s[0].modem_status.delta_cts = 1; - BX_SER_THIS s[0].ms_ipending = 1; - } - if (BX_SER_THIS s[0].modem_status.dsr != prev_dsr) { - BX_SER_THIS s[0].modem_status.delta_dsr = 1; - BX_SER_THIS s[0].ms_ipending = 1; - } - if (BX_SER_THIS s[0].modem_status.ri != prev_ri) - BX_SER_THIS s[0].ms_ipending = 1; - if ((BX_SER_THIS s[0].modem_status.ri == 0) && (prev_ri == 1)) - BX_SER_THIS s[0].modem_status.ri_trailedge = 1; - if (BX_SER_THIS s[0].modem_status.dcd != prev_dcd) { - BX_SER_THIS s[0].modem_status.delta_dcd = 1; - BX_SER_THIS s[0].ms_ipending = 1; - } - raise_interrupt(0, BX_SER_INT_MODSTAT); - } else { - /* set these to 0 for the time being */ - BX_SER_THIS s[0].modem_status.cts = 0; - BX_SER_THIS s[0].modem_status.dsr = 0; - BX_SER_THIS s[0].modem_status.ri = 0; - BX_SER_THIS s[0].modem_status.dcd = 0; - } - break; - - case 0x03FD: /* Line status register */ - BX_ERROR(("write to line status register ignored")); - break; - - case 0x03FE: /* MODEM status register */ - BX_ERROR(("write to MODEM status register ignored")); - break; - - case 0x03FF: /* scratch register */ - BX_SER_THIS s[0].scratch = value; - break; - - default: - BX_PANIC(("unsupported io write to address=0x%04x, value = 0x%02x!", - (unsigned) address, (unsigned) value)); - break; - } -} - - -void -bx_serial_c::rx_fifo_enq(Bit8u port, Bit8u data) -{ - bx_bool gen_int = 0; - - if (BX_SER_THIS s[port].fifo_cntl.enable) { - if (BX_SER_THIS s[port].rx_fifo_end == 16) { - BX_ERROR(("com%d: receive FIFO overflow", port + 1)); - BX_SER_THIS s[port].line_status.overrun_error = 1; - raise_interrupt(port, BX_SER_INT_RXLSTAT); - } else { - BX_SER_THIS s[port].rx_fifo[BX_SER_THIS s[0].rx_fifo_end++] = data; - switch (BX_SER_THIS s[port].fifo_cntl.rxtrigger) { - case 1: - if (BX_SER_THIS s[0].rx_fifo_end == 4) gen_int = 1; - break; - case 2: - if (BX_SER_THIS s[0].rx_fifo_end == 8) gen_int = 1; - break; - case 3: - if (BX_SER_THIS s[0].rx_fifo_end == 14) gen_int = 1; - break; - default: - gen_int = 1; - } - if (gen_int) { - bx_pc_system.deactivate_timer(BX_SER_THIS s[0].fifo_timer_index); - BX_SER_THIS s[port].line_status.rxdata_ready = 1; - raise_interrupt(port, BX_SER_INT_RXDATA); - } else { - bx_pc_system.activate_timer(BX_SER_THIS s[0].fifo_timer_index, - (int) (1000000.0 / BX_SER_THIS s[0].baudrate * - (BX_SER_THIS s[0].line_cntl.wordlen_sel + 5) * 16), - 0); /* not continuous */ - } - } - } else { - if (BX_SER_THIS s[port].line_status.rxdata_ready == 1) { - BX_ERROR(("com%d: overrun error", port + 1)); - BX_SER_THIS s[port].line_status.overrun_error = 1; - raise_interrupt(port, BX_SER_INT_RXLSTAT); - } - BX_SER_THIS s[port].rxbuffer = data; - BX_SER_THIS s[port].line_status.rxdata_ready = 1; - raise_interrupt(port, BX_SER_INT_RXDATA); - } -} - - -void -bx_serial_c::tx_timer_handler(void *this_ptr) -{ - bx_serial_c *class_ptr = (bx_serial_c *) this_ptr; - - class_ptr->tx_timer(); -} - - -void -bx_serial_c::tx_timer(void) -{ - bx_bool gen_int = 0; - - if (BX_SER_THIS s[0].modem_cntl.local_loopback) { - rx_fifo_enq(0, BX_SER_THIS s[0].tsrbuffer); - } else { -#if USE_RAW_SERIAL - if (!BX_SER_THIS raw->ready_transmit()) - BX_PANIC(("Not ready to transmit")); - BX_SER_THIS raw->transmit(BX_SER_THIS s[0].tsrbuffer); -#endif -#if defined(SERIAL_ENABLE) - BX_DEBUG(("write: '%c'", BX_SER_THIS s[0].tsrbuffer)); - if (tty_id >= 0) write(tty_id, (bx_ptr_t) & BX_SER_THIS s[0].tsrbuffer, 1); -#endif - } - - BX_SER_THIS s[0].line_status.tsr_empty = 1; - if (BX_SER_THIS s[0].fifo_cntl.enable && (BX_SER_THIS s[0].tx_fifo_end > 0)) { - BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].tx_fifo[0]; - BX_SER_THIS s[0].line_status.tsr_empty = 0; - memcpy(&BX_SER_THIS s[0].tx_fifo[0], &BX_SER_THIS s[0].tx_fifo[1], 15); - gen_int = (--BX_SER_THIS s[0].tx_fifo_end == 0); - } else if (!BX_SER_THIS s[0].line_status.thr_empty) { - BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].thrbuffer; - BX_SER_THIS s[0].line_status.tsr_empty = 0; - gen_int = 1; - } - if (!BX_SER_THIS s[0].line_status.tsr_empty) { - if (gen_int) { - BX_SER_THIS s[0].line_status.thr_empty = 1; - raise_interrupt(0, BX_SER_INT_TXHOLD); - } - bx_pc_system.activate_timer(BX_SER_THIS s[0].tx_timer_index, - (int) (1000000.0 / BX_SER_THIS s[0].baudrate * - (BX_SER_THIS s[0].line_cntl.wordlen_sel + 5)), - 0); /* not continuous */ - } -} - - -void -bx_serial_c::rx_timer_handler(void *this_ptr) -{ - bx_serial_c *class_ptr = (bx_serial_c *) this_ptr; - - class_ptr->rx_timer(); -} - - -void -bx_serial_c::rx_timer(void) -{ -#if BX_HAVE_SELECT -#ifndef __BEOS__ - struct timeval tval; - fd_set fds; -#endif -#endif - int bdrate = BX_SER_THIS s[0].baudrate / (BX_SER_THIS s[0].line_cntl.wordlen_sel + 5); - unsigned char chbuf = 0; - -#if BX_HAVE_SELECT -#ifndef __BEOS__ - tval.tv_sec = 0; - tval.tv_usec = 0; - -// MacOS: I'm not sure what to do with this, since I don't know -// what an fd_set is or what FD_SET() or select() do. They aren't -// declared in the CodeWarrior standard library headers. I'm just -// leaving it commented out for the moment. - - FD_ZERO(&fds); - if (tty_id >= 0) FD_SET(tty_id, &fds); - - if ((BX_SER_THIS s[0].line_status.rxdata_ready == 0) || - (BX_SER_THIS s[0].fifo_cntl.enable)) { -#if USE_RAW_SERIAL - bx_bool rdy; - uint16 data; - if ((rdy = BX_SER_THIS raw->ready_receive())) { - data = BX_SER_THIS raw->receive(); - if (data == C_BREAK) { - BX_DEBUG(("got BREAK")); - BX_SER_THIS s[0].line_status.break_int = 1; - rdy = 0; - } - } - if (rdy) { - chbuf = data; -#elif defined(SERIAL_ENABLE) - if ((tty_id >= 0) && (select(tty_id + 1, &fds, NULL, NULL, &tval) == 1)) { - (void) read(tty_id, &chbuf, 1); - BX_DEBUG(("read: '%c'",chbuf)); -#else - if (0) { -#endif - if (!BX_SER_THIS s[0].modem_cntl.local_loopback) { - rx_fifo_enq(0, chbuf); - } - } else { - if (!BX_SER_THIS s[0].fifo_cntl.enable) { - bdrate = (int) (1000000.0 / 100000); // Poll frequency is 100ms - } - } - } else { - // Poll at 4x baud rate to see if the next-char can - // be read - bdrate *= 4; - } -#endif -#endif - - bx_pc_system.activate_timer(BX_SER_THIS s[0].rx_timer_index, - (int) (1000000.0 / bdrate), - 0); /* not continuous */ -} - - -void -bx_serial_c::fifo_timer_handler(void *this_ptr) -{ - bx_serial_c *class_ptr = (bx_serial_c *) this_ptr; - - class_ptr->fifo_timer(); -} - - -void -bx_serial_c::fifo_timer(void) -{ - BX_SER_THIS s[0].line_status.rxdata_ready = 1; - raise_interrupt(0, BX_SER_INT_FIFO); -} diff --git a/tools/ioemu/iodev/serial.h b/tools/ioemu/iodev/serial.h deleted file mode 100644 index 00f01c976e..0000000000 --- a/tools/ioemu/iodev/serial.h +++ /dev/null @@ -1,193 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: serial.h,v 1.15 2003/11/16 08:21:10 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -// Peter Grehan (grehan@iprg.nokia.com) coded most of this -// serial emulation. - -#if USE_RAW_SERIAL -#include "serial_raw.h" -#endif // USE_RAW_SERIAL - -#if BX_USE_SER_SMF -# define BX_SER_SMF static -# define BX_SER_THIS theSerialDevice-> -#else -# define BX_SER_SMF -# define BX_SER_THIS this-> -#endif - -#define BX_SERIAL_MAXDEV 4 - -#define BX_PC_CLOCK_XTL 1843200.0 - -#define BX_SER_RXIDLE 0 -#define BX_SER_RXPOLL 1 -#define BX_SER_RXWAIT 2 - -enum { - BX_SER_INT_IER, - BX_SER_INT_RXDATA, - BX_SER_INT_TXHOLD, - BX_SER_INT_RXLSTAT, - BX_SER_INT_MODSTAT, - BX_SER_INT_FIFO -}; - -typedef struct { - /* - * UART internal state - */ - bx_bool ls_interrupt; - bx_bool ms_interrupt; - bx_bool rx_interrupt; - bx_bool tx_interrupt; - bx_bool fifo_interrupt; - bx_bool ls_ipending; - bx_bool ms_ipending; - bx_bool rx_ipending; - bx_bool fifo_ipending; - - Bit8u IRQ; - - Bit8u rx_fifo_end; - Bit8u tx_fifo_end; - - int baudrate; - int tx_timer_index; - - int rx_pollstate; - int rx_timer_index; - int fifo_timer_index; - - /* - * Register definitions - */ - Bit8u rxbuffer; /* receiver buffer register (r/o) */ - Bit8u thrbuffer; /* transmit holding register (w/o) */ - /* Interrupt Enable Register */ - struct { - bx_bool rxdata_enable; /* 1=enable receive data interrupts */ - bx_bool txhold_enable; /* 1=enable tx. holding reg. empty ints */ - bx_bool rxlstat_enable; /* 1=enable rx line status interrupts */ - bx_bool modstat_enable; /* 1=enable modem status interrupts */ - } int_enable; - /* Interrupt Identification Register (r/o) */ - struct { - bx_bool ipending; /* 0=interrupt pending */ - Bit8u int_ID; /* 3-bit interrupt ID */ - } int_ident; - /* FIFO Control Register (w/o) */ - struct { - bx_bool enable; /* 1=enable tx and rx FIFOs */ - Bit8u rxtrigger; /* 2-bit code for rx fifo trigger level */ - } fifo_cntl; - /* Line Control Register (r/w) */ - struct { - Bit8u wordlen_sel; /* 2-bit code for char length */ - bx_bool stopbits; /* select stop bit len */ - bx_bool parity_enable; /* ... */ - bx_bool evenparity_sel; /* ... */ - bx_bool stick_parity; /* ... */ - bx_bool break_cntl; /* 1=send break signal */ - bx_bool dlab; /* divisor latch access bit */ - } line_cntl; - /* MODEM Control Register (r/w) */ - struct { - bx_bool dtr; /* DTR output value */ - bx_bool rts; /* RTS output value */ - bx_bool out1; /* OUTPUT1 value */ - bx_bool out2; /* OUTPUT2 value */ - bx_bool local_loopback; /* 1=loopback mode */ - } modem_cntl; - /* Line Status Register (r/w) */ - struct { - bx_bool rxdata_ready; /* 1=receiver data ready */ - bx_bool overrun_error; /* 1=receive overrun detected */ - bx_bool parity_error; /* 1=rx char has a bad parity bit */ - bx_bool framing_error; /* 1=no stop bit detected for rx char */ - bx_bool break_int; /* 1=break signal detected */ - bx_bool thr_empty; /* 1=tx hold register (or fifo) is empty */ - bx_bool tsr_empty; /* 1=shift reg and hold reg empty */ - bx_bool fifo_error; /* 1=at least 1 err condition in fifo */ - } line_status; - /* Modem Status Register (r/w) */ - struct { - bx_bool delta_cts; /* 1=CTS changed since last read */ - bx_bool delta_dsr; /* 1=DSR changed since last read */ - bx_bool ri_trailedge; /* 1=RI moved from low->high */ - bx_bool delta_dcd; /* 1=CD changed since last read */ - bx_bool cts; /* CTS input value */ - bx_bool dsr; /* DSR input value */ - bx_bool ri; /* RI input value */ - bx_bool dcd; /* DCD input value */ - } modem_status; - - Bit8u scratch; /* Scratch Register (r/w) */ - Bit8u tsrbuffer; /* transmit shift register (internal) */ - Bit8u rx_fifo[16]; /* receive FIFO (internal) */ - Bit8u tx_fifo[16]; /* transmit FIFO (internal) */ - Bit8u divisor_lsb; /* Divisor latch, least-sig. byte */ - Bit8u divisor_msb; /* Divisor latch, most-sig. byte */ -} bx_serial_t; - - - -class bx_serial_c : public bx_devmodel_c { -public: - bx_serial_c(void); - ~bx_serial_c(void); - virtual void init(void); - virtual void reset(unsigned type); -#if USE_RAW_SERIAL - serial_raw* raw; -#endif // USE_RAW_SERIAL - -private: - bx_serial_t s[BX_SERIAL_MAXDEV]; - - static void lower_interrupt(Bit8u port); - static void raise_interrupt(Bit8u port, int type); - - static void rx_fifo_enq(Bit8u port, Bit8u data); - - static void tx_timer_handler(void *); - BX_SER_SMF void tx_timer(void); - - static void rx_timer_handler(void *); - BX_SER_SMF void rx_timer(void); - - static void fifo_timer_handler(void *); - BX_SER_SMF void fifo_timer(void); - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); -#if !BX_USE_SER_SMF - Bit32u read(Bit32u address, unsigned io_len); - void write(Bit32u address, Bit32u value, unsigned io_len); -#endif - }; - diff --git a/tools/ioemu/iodev/serial_raw.h b/tools/ioemu/iodev/serial_raw.h deleted file mode 100644 index 978c28d29b..0000000000 --- a/tools/ioemu/iodev/serial_raw.h +++ /dev/null @@ -1,23 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: serial_raw.h,v 1.2 2001/10/03 13:10:38 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -#include - -#define P_EVEN 0 -#define P_ODD 1 -#define C_BREAK 201 - -class serial_raw : public logfunctions { - public: - serial_raw (char *ttypath, int signal); - void set_baudrate (int rate); - void set_data_bits (int ); - void set_stop_bits (int); - void set_parity_mode (int, int); - void transmit (int byte); - void send_hangup (); - int ready_transmit (); - int ready_receive (); - int receive (); -}; diff --git a/tools/ioemu/iodev/slowdown_timer.cc b/tools/ioemu/iodev/slowdown_timer.cc deleted file mode 100644 index 76d8613ec8..0000000000 --- a/tools/ioemu/iodev/slowdown_timer.cc +++ /dev/null @@ -1,182 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: slowdown_timer.cc,v 1.17.2.1 2004/02/06 22:14:36 danielg4 Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -// - -#include "bochs.h" -#include - -//These need to stay printfs because they are useless in the log file. -#define BX_SLOWDOWN_PRINTF_FEEDBACK 0 - -#define SECINUSEC 1000000 -#define usectosec(a) ((a)/SECINUSEC) -#define sectousec(a) ((a)*SECINUSEC) -#define nsectousec(a) ((a)/1000) - -#define MSECINUSEC 1000 -#define usectomsec(a) ((a)/MSECINUSEC) - -#if BX_HAVE_USLEEP -# define Qval 1000 -#else -# define Qval SECINUSEC -#endif - -#define MAXMULT 1.5 -#define REALTIME_Q SECINUSEC - -#define LOG_THIS bx_slowdown_timer. - -bx_slowdown_timer_c bx_slowdown_timer; - -bx_slowdown_timer_c::bx_slowdown_timer_c() { - put("STIMER"); - settype(STIMERLOG); - - - s.start_time=0; - s.start_emulated_time=0; - s.timer_handle=BX_NULL_TIMER_HANDLE; -} - -void -bx_slowdown_timer_c::init(void) { - - // Return early if slowdown timer not selected - if ( (bx_options.clock.Osync->get () != BX_CLOCK_SYNC_SLOWDOWN) - && (bx_options.clock.Osync->get () != BX_CLOCK_SYNC_BOTH) ) - return; - - BX_INFO(("using 'slowdown' timer synchronization method")); - s.MAXmultiplier=MAXMULT; - s.Q=Qval; - - if(s.MAXmultiplier<1) - s.MAXmultiplier=1; - - s.start_time=sectousec(time(NULL)); - s.start_emulated_time = bx_pc_system.time_usec(); - s.lasttime=0; - if (s.timer_handle == BX_NULL_TIMER_HANDLE) { - s.timer_handle=bx_pc_system.register_timer(this, timer_handler, 100 , 1, 1, - "slowdown_timer"); - } - bx_pc_system.deactivate_timer(s.timer_handle); - bx_pc_system.activate_timer(s.timer_handle,(Bit32u)s.Q,0); -} - -void -bx_slowdown_timer_c::reset(unsigned type) -{ -} - -void -bx_slowdown_timer_c::timer_handler(void * this_ptr) { - bx_slowdown_timer_c * class_ptr = (bx_slowdown_timer_c *) this_ptr; - - class_ptr->handle_timer(); -} - -void -bx_slowdown_timer_c::handle_timer() { - Bit64u total_emu_time = (bx_pc_system.time_usec()) - s.start_emulated_time; - Bit64u wanttime = s.lasttime+s.Q; - Bit64u totaltime = sectousec(time(NULL)) - s.start_time; - Bit64u thistime=(wanttime>totaltime)?wanttime:totaltime; - -#if BX_SLOWDOWN_PRINTF_FEEDBACK - printf("Entering slowdown timer handler.\n"); -#endif - - /* Decide if we're behind. - * Set interrupt interval accordingly. */ - if(totaltime > total_emu_time) { - bx_pc_system.deactivate_timer(s.timer_handle); - bx_pc_system.activate_timer(s.timer_handle, - (Bit32u)(s.MAXmultiplier * (float)((Bit64s)s.Q)), - 0); -#if BX_SLOWDOWN_PRINTF_FEEDBACK - printf("running at MAX speed\n"); -#endif - } else { - bx_pc_system.deactivate_timer(s.timer_handle); - bx_pc_system.activate_timer(s.timer_handle,s.Q,0); -#if BX_SLOWDOWN_PRINTF_FEEDBACK - printf("running at NORMAL speed\n"); -#endif - } - - /* Make sure we took at least one time quantum. */ - /* This is a little strange. I'll try to explain. - * We're running bochs one second ahead of real time. - * this gives us a very precise division on whether - * we're ahead or behind the second line. - * Basically, here's how it works: - * *****|******************|***********... - * Time Time+1sec - * <^Bochs doesn't delay. - * ^>Bochs delays. - * <^Bochs runs at MAX speed. - * ^>Bochs runs at normal - */ - if(wanttime > (totaltime+REALTIME_Q)) { -#if BX_HAVE_USLEEP - usleep(s.Q); -#elif BX_HAVE_MSLEEP - msleep(usectomsec(s.Q)); -#elif BX_HAVE_SLEEP - sleep(usectosec(s.Q)); -#else -#error do not know have to sleep -#endif //delay(wanttime-totaltime); - /*alternatively: delay(Q); - * This works okay because we share the delay between - * two time quantums. - */ -#if BX_SLOWDOWN_PRINTF_FEEDBACK - printf("DELAYING for a quantum\n"); -#endif - } - s.lasttime=thistime; - - //Diagnostic info: -#if 0 - if(wanttime > (totaltime+REALTIME_Q)) { - if(totaltime > total_emu_time) { - printf("Solving OpenBSD problem.\n"); - } else { - printf("too fast.\n"); - } - } else { - if(totaltime > total_emu_time) { - printf("too slow.\n"); - } else { - printf("sometimes invalid state, normally okay.\n"); - } - } -#endif // Diagnostic info -} - diff --git a/tools/ioemu/iodev/slowdown_timer.h b/tools/ioemu/iodev/slowdown_timer.h deleted file mode 100644 index 3b6b153a71..0000000000 --- a/tools/ioemu/iodev/slowdown_timer.h +++ /dev/null @@ -1,33 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: slowdown_timer.h,v 1.8 2003/08/19 00:10:38 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// - -class bx_slowdown_timer_c : public logfunctions { - -private: - struct { - Bit64u start_time; - Bit64u start_emulated_time; - Bit64u lasttime; - - int timer_handle; - - float MAXmultiplier; - Bit64u Q; // (Q (in seconds)) - } s; - -public: - bx_slowdown_timer_c(); - - void init(void); - void reset(unsigned type); - - static void timer_handler(void * this_ptr); - - void handle_timer(); - -}; - -extern bx_slowdown_timer_c bx_slowdown_timer; - diff --git a/tools/ioemu/iodev/soundlnx.cc b/tools/ioemu/iodev/soundlnx.cc deleted file mode 100644 index 773addc311..0000000000 --- a/tools/ioemu/iodev/soundlnx.cc +++ /dev/null @@ -1,227 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: soundlnx.cc,v 1.6 2002/12/24 10:12:26 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// This file (SOUNDLNX.CC) written and donated by Josef Drexler - - -#include "bochs.h" -#if (defined(linux) || defined(__FreeBSD__)) && BX_SUPPORT_SB16 -#define LOG_THIS bx_sb16. - -#include -#include -#include - -bx_sound_linux_c::bx_sound_linux_c(bx_sb16_c *sb16) - :bx_sound_output_c(sb16) -{ - this->sb16 = sb16; - midi = NULL; - wavedevice = NULL; - wave = -1; -} - -bx_sound_linux_c::~bx_sound_linux_c() -{ - // nothing for now -} - - -int bx_sound_linux_c::waveready() -{ - return BX_SOUND_OUTPUT_OK; -} - -int bx_sound_linux_c::midiready() -{ - return BX_SOUND_OUTPUT_OK; -} - -int bx_sound_linux_c::openmidioutput(char *device) -{ - if ( (device == NULL) || (strlen(device) < 1) ) - return BX_SOUND_OUTPUT_ERR; - - midi = fopen(device,"w"); - - if (midi == NULL) - { - WRITELOG( MIDILOG(2), "Couldn't open midi output device %s: %s.", - device, strerror(errno)); - return BX_SOUND_OUTPUT_ERR; - } - - return BX_SOUND_OUTPUT_OK; -} - - -int bx_sound_linux_c::sendmidicommand(int delta, int command, int length, Bit8u data[]) -{ - UNUSED(delta); - // BX_PANIC(("Sendmidicommand!!"); - - fputc(command, midi); - fwrite(data, 1, length, midi); - fflush(midi); // to start playing immediately - - return BX_SOUND_OUTPUT_OK; -} - - -int bx_sound_linux_c::closemidioutput() -{ - fclose(midi); - - return BX_SOUND_OUTPUT_OK; -} - - -int bx_sound_linux_c::openwaveoutput(char *device) -{ - int length = strlen(device) + 1; - - if (wavedevice != NULL) - delete(wavedevice); - - wavedevice = new char[length]; - - if (wavedevice == NULL) - return BX_SOUND_OUTPUT_ERR; - - strncpy(wavedevice, device, length); - - return BX_SOUND_OUTPUT_OK; -} - -int bx_sound_linux_c::startwaveplayback(int frequency, int bits, int stereo, int format) -{ - int fmt, ret; - int signeddata = format & 1; - - if ( (wavedevice == NULL) || (strlen(wavedevice) < 1) ) - return BX_SOUND_OUTPUT_ERR; - - if (wave == -1) - wave = open(wavedevice, O_WRONLY); - else - if ( (frequency == oldfreq) && - (bits == oldbits) && - (stereo == oldstereo) && - (format == oldformat) ) - return BX_SOUND_OUTPUT_OK; // nothing to do - - oldfreq = frequency; - oldbits = bits; - oldstereo = stereo; - oldformat = format; - - if (wave == -1) - return BX_SOUND_OUTPUT_ERR; - - if (bits == 16) - if (signeddata == 1) - fmt = AFMT_S16_LE; - else - fmt = AFMT_U16_LE; - else if (bits == 8) - if (signeddata == 1) - fmt = AFMT_S8; - else - fmt = AFMT_U8; - else - return BX_SOUND_OUTPUT_ERR; - - // set frequency etc. - ret = ioctl(wave, SNDCTL_DSP_RESET); - if (ret != 0) - WRITELOG( WAVELOG(4), "ioctl(SNDCTL_DSP_RESET): %s", strerror(errno)); - - /* - ret = ioctl(wave, SNDCTL_DSP_SETFRAGMENT, &fragment); - if (ret != 0) - WRITELOG( WAVELOG(4), "ioctl(SNDCTL_DSP_SETFRAGMENT, %d): %s", - fragment, strerror(errno)); - */ - - ret = ioctl(wave, SNDCTL_DSP_SETFMT, &fmt); - if (ret != 0) // abort if the format is unknown, to avoid playing noise - { - WRITELOG( WAVELOG(4), "ioctl(SNDCTL_DSP_SETFMT, %d): %s", - fmt, strerror(errno)); - return BX_SOUND_OUTPUT_ERR; - } - - ret = ioctl(wave, SNDCTL_DSP_STEREO, &stereo); - if (ret != 0) - WRITELOG( WAVELOG(4), "ioctl(SNDCTL_DSP_STEREO, %d): %s", - stereo, strerror(errno)); - - ret = ioctl(wave, SNDCTL_DSP_SPEED, &frequency); - if (ret != 0) - WRITELOG( WAVELOG(4), "ioctl(SNDCTL_DSP_SPEED, %d): %s", - frequency, strerror(errno)); - - // ioctl(wave, SNDCTL_DSP_GETBLKSIZE, &fragment); - // WRITELOG( WAVELOG(4), "current output block size is %d", fragment); - - return BX_SOUND_OUTPUT_OK; -} - -int bx_sound_linux_c::sendwavepacket(int length, Bit8u data[]) -{ - int ret; - - ret = write(wave, data, length); - - return BX_SOUND_OUTPUT_OK; -} - -int bx_sound_linux_c::stopwaveplayback() -{ - // ioctl(wave, SNDCTL_DSP_SYNC); - // close(wave); - // wave = -1; - - return BX_SOUND_OUTPUT_OK; -} - -int bx_sound_linux_c::closewaveoutput() -{ - if (wavedevice != NULL) - delete(wavedevice); - - if (wave != -1) - { - close(wave); - wave = -1; - } - - wavedevice = NULL; - - return BX_SOUND_OUTPUT_OK; -} - -#endif // defined(linux) diff --git a/tools/ioemu/iodev/soundlnx.h b/tools/ioemu/iodev/soundlnx.h deleted file mode 100644 index 8f718b5acd..0000000000 --- a/tools/ioemu/iodev/soundlnx.h +++ /dev/null @@ -1,69 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: soundlnx.h,v 1.5 2002/12/24 10:12:26 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// This file (SOUNDLNX.H) written and donated by Josef Drexler - - -#if (defined(linux) || defined(__FreeBSD__)) - -#include "bochs.h" - -#define BX_SOUND_LINUX_BUFSIZE BX_SOUND_OUTPUT_WAVEPACKETSIZE - -class bx_sound_linux_c : public bx_sound_output_c { -public: - bx_sound_linux_c(bx_sb16_c *sb16); - BX_SOUND_VIRTUAL ~bx_sound_linux_c(); - - // if virtual functions are used, we have to override them - // and define our own. Otherwise this file will just implement - // the original functions -#ifdef BX_USE_SOUND_VIRTUAL - BX_SOUND_VIRTUAL int waveready(); - BX_SOUND_VIRTUAL int midiready(); - - BX_SOUND_VIRTUAL int openmidioutput(char *device); - BX_SOUND_VIRTUAL int sendmidicommand(int delta, int command, int length, Bit8u data[]); - BX_SOUND_VIRTUAL int closemidioutput(); - - BX_SOUND_VIRTUAL int openwaveoutput(char *device); - BX_SOUND_VIRTUAL int startwaveplayback(int frequency, int bits, int stereo, int format); - BX_SOUND_VIRTUAL int sendwavepacket(int length, Bit8u data[]); - BX_SOUND_VIRTUAL int stopwaveplayback(); - BX_SOUND_VIRTUAL int closewaveoutput(); -#endif - -private: - bx_sb16_c *sb16; - FILE *midi; - char *wavedevice; - int wave; - int bufferpos; - Bit8u audio_buffer[BX_SOUND_LINUX_BUFSIZE]; - int oldfreq,oldbits,oldstereo,oldformat; -}; - -#endif // defined(linux) diff --git a/tools/ioemu/iodev/soundwin.cc b/tools/ioemu/iodev/soundwin.cc deleted file mode 100644 index b8b386cae4..0000000000 --- a/tools/ioemu/iodev/soundwin.cc +++ /dev/null @@ -1,521 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: soundwin.cc,v 1.13 2003/04/05 08:26:49 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// This file (SOUNDWIN.CC) written and donated by Josef Drexler - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" -#if defined(WIN32) && BX_SUPPORT_SB16 - -#define LOG_THIS bx_devices.pluginSB16Device-> - -bx_sound_windows_c::bx_sound_windows_c(bx_sb16_c *sb16) - :bx_sound_output_c(sb16) -{ - this->sb16 = sb16; - - MidiOpen = 0; - WaveOpen = 0; - - ismidiready = 1; - iswaveready = 1; - - // size is the total size of the midi header and buffer and the - // BX_SOUND_WINDOWS_NBUF wave header and buffers, all aligned - // on a 16-byte boundary - -#define ALIGN(size) ( (size + 15) & ~15 ) - -#define size ALIGN(sizeof(MIDIHDR)) \ - + ALIGN(sizeof(WAVEHDR)) \ - + ALIGN(BX_SOUND_WINDOWS_MAXSYSEXLEN) * BX_SOUND_WINDOWS_NBUF \ - + ALIGN(BX_SOUND_OUTPUT_WAVEPACKETSIZE) * BX_SOUND_WINDOWS_NBUF - - DataHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, size); - DataPointer = (Bit8u*) GlobalLock(DataHandle); - - if (DataPointer == NULL) - BX_PANIC(("GlobalLock returned NULL-pointer")); - -#define NEWBUFFER(size) &(DataPointer[offset]); offset += ALIGN(size) - - int offset = 0; - MidiHeader = (LPMIDIHDR) NEWBUFFER(sizeof(MIDIHDR)); - MidiData = (LPSTR) NEWBUFFER(BX_SOUND_WINDOWS_MAXSYSEXLEN); - - for (int bufnum=0; bufnum size) - BX_PANIC(("Allocated memory was too small!")); - -#undef size -#undef ALIGN -#undef NEWBUFFER -} - -bx_sound_windows_c::~bx_sound_windows_c() -{ - GlobalUnlock(DataHandle); - GlobalFree(DataHandle); -} - -int bx_sound_windows_c::waveready() -{ - if (iswaveready == 0) - checkwaveready(); - - if (iswaveready == 1) - return BX_SOUND_OUTPUT_OK; - else - return BX_SOUND_OUTPUT_ERR; -} -int bx_sound_windows_c::midiready() -{ - if (ismidiready == 0) - checkmidiready(); - - if (ismidiready == 1) - return BX_SOUND_OUTPUT_OK; - else - return BX_SOUND_OUTPUT_ERR; -} - -int bx_sound_windows_c::openmidioutput(char *device) -{ - // could make the output device selectable, - // but currently only the midi mapper is supported - UNUSED(device); - - UINT deviceid = (UINT) MIDIMAPPER; - - MidiOpen = 0; - - UINT ret = midiOutOpen( &MidiOut, deviceid, 0, 0, CALLBACK_NULL); - if (ret == 0) - MidiOpen = 1; - - WRITELOG( MIDILOG(4), "midiOutOpen() = %d, MidiOpen: %d", ret, MidiOpen); - - return (MidiOpen == 1) ? BX_SOUND_OUTPUT_OK : BX_SOUND_OUTPUT_ERR; -} - -int bx_sound_windows_c::sendmidicommand(int delta, int command, int length, Bit8u data[]) -{ - UINT ret; - - if (MidiOpen != 1) - return BX_SOUND_OUTPUT_ERR; - - if ( (command == 0xf0) || (command == 0xf7) || (length > 3) ) - { - WRITELOG( WAVELOG(5), "SYSEX started, length %d", length); - ismidiready = 0; // until the buffer is done - memcpy(MidiData, data, length); - MidiHeader->lpData = MidiData; - MidiHeader->dwBufferLength = BX_SOUND_WINDOWS_MAXSYSEXLEN; - MidiHeader->dwBytesRecorded = 0; - MidiHeader->dwUser = 0; - MidiHeader->dwFlags = 0; - ret = midiOutPrepareHeader(MidiOut, MidiHeader, sizeof(*MidiHeader)); - if (ret != 0) - WRITELOG( MIDILOG(2), "midiOutPrepareHeader() = %d", ret); - ret = midiOutLongMsg(MidiOut, MidiHeader, sizeof(*MidiHeader)); - if (ret != 0) - WRITELOG( MIDILOG(2), "midiOutLongMsg() = %d", ret); - } - else - { - DWORD msg = command; - - for (int i = 0; idwFlags = WHDR_DONE; - - head = 0; - tailfull = 0; - tailplay = 0; - needreopen = 0; -#endif - - return BX_SOUND_OUTPUT_OK; -} - -int bx_sound_windows_c::playnextbuffer() -{ - UINT ret; - PCMWAVEFORMAT waveformat; - int bufnum; - - // if the format is different, we have to reopen the device, - // so reset it first - if (needreopen != 0) - if (WaveOpen != 0) - ret = waveOutReset( WaveOut ); - - // clean up the buffers and mark if output is ready - checkwaveready(); - - // do we have to play anything? - if (tailplay == head) - return BX_SOUND_OUTPUT_OK; - - // if the format is different, we have to close and reopen the device - // or, just open the device if it's not open yet - if ( (needreopen != 0) || (WaveOpen == 0) ) - { - if (WaveOpen != 0) - { - ret = waveOutClose( WaveOut ); - WaveOpen = 0; - } - - // try three times to find a suitable format - for (int tries = 0; tries < 3; tries++) - { - int frequency = WaveInfo.frequency; - int stereo = WaveInfo.stereo; - int bits = WaveInfo.bits; - int format = WaveInfo.format; - int bps = (bits / 8) * (stereo + 1); - - waveformat.wf.wFormatTag = WAVE_FORMAT_PCM; - waveformat.wf.nChannels = stereo + 1; - waveformat.wf.nSamplesPerSec = frequency; - waveformat.wf.nAvgBytesPerSec = frequency * bps; - waveformat.wf.nBlockAlign = bps; - waveformat.wBitsPerSample = bits; - - ret = waveOutOpen( &(WaveOut), WaveDevice, (LPWAVEFORMATEX)&(waveformat.wf), 0, 0, CALLBACK_NULL); - if (ret != 0) - { - char errormsg[4*MAXERRORLENGTH+1]; - waveOutGetErrorTextA(ret, errormsg, 4*MAXERRORLENGTH+1); - WRITELOG( WAVELOG(5), "waveOutOpen: %s", errormsg); - switch (tries) - { - case 0: // maybe try a different frequency - if (frequency < 15600) - frequency = 11025; - else if (frequency < 31200) - frequency = 22050; - else - frequency = 44100; - - WRITELOG( WAVELOG(4), "Couldn't open wave device (error %d), trying frequency %d", ret, frequency); - - break; - case 1: // or something else - frequency = 11025; - stereo = 0; - bits = 8; - bps = 1; - - WRITELOG( WAVELOG(4), "Couldn't open wave device again (error %d), trying 11KHz, mono, 8bit", ret); - - break; - case 2: // nope, doesn't work - - WRITELOG( WAVELOG(2), "Couldn't open wave device (error %d)!", ret); - - return BX_SOUND_OUTPUT_ERR; - } - WRITELOG( WAVELOG(5), "The format was: wFormatTag=%d, nChannels=%d, nSamplesPerSec=%d,", - waveformat.wf.wFormatTag, waveformat.wf.nChannels, waveformat.wf.nSamplesPerSec); - WRITELOG( WAVELOG(5), " nAvgBytesPerSec=%d, nBlockAlign=%d, wBitsPerSample=%d", - waveformat.wf.nAvgBytesPerSec, waveformat.wf.nBlockAlign, waveformat.wBitsPerSample); - - } - else - { - WaveOpen = 1; - needreopen = 0; - break; - } - } - } - - for (bufnum=tailplay; bufnum != head; - bufnum++, bufnum &= BX_SOUND_WINDOWS_NMASK, tailplay=bufnum) - { - WRITELOG( WAVELOG(5), "Playing buffer %d", bufnum); - - // prepare the wave header - WaveHeader[bufnum]->lpData = WaveData[bufnum]; - WaveHeader[bufnum]->dwBufferLength = length[bufnum]; - WaveHeader[bufnum]->dwBytesRecorded = length[bufnum]; - WaveHeader[bufnum]->dwUser = 0; - WaveHeader[bufnum]->dwFlags = 0; - WaveHeader[bufnum]->dwLoops = 1; - - ret = waveOutPrepareHeader(WaveOut, WaveHeader[bufnum], sizeof(*WaveHeader[bufnum])); - if (ret != 0) - { - WRITELOG( WAVELOG(2), "waveOutPrepareHeader = %d", ret); - return BX_SOUND_OUTPUT_ERR; - } - - ret = waveOutWrite(WaveOut, WaveHeader[bufnum], sizeof(*WaveHeader[bufnum])); - if (ret != 0) - { - char errormsg[4*MAXERRORLENGTH+1]; - waveOutGetErrorTextA(ret, errormsg, 4*MAXERRORLENGTH+1); - WRITELOG( WAVELOG(5), "waveOutWrite: %s", errormsg); - } - } - return BX_SOUND_OUTPUT_OK; -} - -int bx_sound_windows_c::startwaveplayback(int frequency, int bits, int stereo, int format) -{ - // UINT ret; - - WRITELOG( WAVELOG(4), "startwaveplayback(%d, %d, %d, %x)", frequency, bits, stereo, format); - -#ifdef usewaveOut - // check if any of the properties have changed - if ( (WaveInfo.frequency != frequency) || - (WaveInfo.bits != bits) || - (WaveInfo.stereo != stereo) || - (WaveInfo.format != format) ) - { - needreopen = 1; - - // store the current settings to be used by sendwavepacket() - WaveInfo.frequency = frequency; - WaveInfo.bits = bits; - WaveInfo.stereo = stereo; - WaveInfo.format = format; - } -#endif - -#ifdef usesndPlaySnd - int bps = (bits / 8) * (stereo + 1); - LPWAVEFILEHEADER header = (LPWAVEFILEHEADER) WaveData; - - memcpy(header->RIFF, "RIFF", 4); - memcpy(header->TYPE, "WAVE", 4); - memcpy(header->chnk, "fmt ", 4); - header->chnklen = 16; - header->waveformat.wf.wFormatTag = WAVE_FORMAT_PCM; - header->waveformat.wf.nChannels = stereo + 1; - header->waveformat.wf.nSamplesPerSec = frequency; - header->waveformat.wf.nAvgBytesPerSec = frequency * bps; - header->waveformat.wf.nBlockAlign = bps; - header->waveformat.wBitsPerSample = bits; - memcpy(header->chnk2, "data", 4); -#endif - - return BX_SOUND_OUTPUT_OK; -} - -int bx_sound_windows_c::sendwavepacket(int length, Bit8u data[]) -{ -// UINT ret; - int bufnum; - - WRITELOG( WAVELOG(4), "sendwavepacket(%d, %p)", length, data); - -#ifdef usewaveOut - bufnum = head; - - memcpy(WaveData[bufnum], data, length); - this->length[bufnum] = length; - - // select next buffer to write to - bufnum++; - bufnum &= BX_SOUND_WINDOWS_NMASK; - - if ( ( (bufnum + 1) & BX_SOUND_WINDOWS_NMASK) == tailfull ) - { // this should not actually happen! - WRITELOG( WAVELOG(2), "Output buffer overflow! Not played. Iswaveready was %d", iswaveready); - iswaveready = 0; // stop the output for a while - return BX_SOUND_OUTPUT_ERR; - } - - head = bufnum; - - // check if more buffers are available, otherwise stall the emulator - if ( ( (bufnum + 2) & BX_SOUND_WINDOWS_NMASK) == tailfull ) - { - WRITELOG( WAVELOG(5), "Buffer status: Head %d, TailFull %d, TailPlay %d. Stall.", - head, tailfull, tailplay); - iswaveready = 0; - } - - playnextbuffer(); - -#endif - -#ifdef usesndPlaySnd - LPWAVEFILEHEADER header = (LPWAVEFILEHEADER) WaveData; - - header->length = length + 36; - header->chnk2len = length; - - memcpy( &(header->data), data, length); - - FILE *test = fopen("test", "a"); - fwrite(WaveData, 1, length + 44, test); - fclose(test); - - ret = sndPlaySoundA( (LPCSTR) header, SND_SYNC | SND_MEMORY ); - if (ret != 0) - { - WRITELOG( WAVELOG(3), "sndPlaySoundA: %d", ret); - } -#endif - - return BX_SOUND_OUTPUT_OK; -} - -int bx_sound_windows_c::stopwaveplayback() -{ - WRITELOG( WAVELOG(4), "stopwaveplayback()"); - -#ifdef usewaveOut - // this is handled by checkwaveready() when closing -#endif - -#ifdef usesndPlaySnd - sndPlaySoundA( NULL, SND_ASYNC | SND_MEMORY ); - - WaveOpen = 0; -#endif - - return BX_SOUND_OUTPUT_OK; -} - -int bx_sound_windows_c::closewaveoutput() -{ -// int bufnum; - - WRITELOG( WAVELOG(4), "closewaveoutput"); - -#ifdef usewaveOut - if (WaveOpen == 1) - { - waveOutReset(WaveOut); - - // let checkwaveready() clean up the buffers - checkwaveready(); - - waveOutClose(WaveOut); - - head = 0; - tailfull = 0; - tailplay = 0; - needreopen = 0; - } -#endif - - return BX_SOUND_OUTPUT_OK; -} - -void bx_sound_windows_c::checkmidiready() -{ - UINT ret; - - if ( (MidiHeader->dwFlags & WHDR_DONE) != 0) - { - WRITELOG( MIDILOG(5), "SYSEX message done, midi ready again."); - ret = midiOutUnprepareHeader( MidiOut, MidiHeader, sizeof(*MidiHeader)); - ismidiready = 1; - } -} -void bx_sound_windows_c::checkwaveready() -{ - int bufnum; - UINT ret; - - // clean up all finished buffers and mark them as available - for (bufnum=tailfull; - (bufnum != tailplay) && - ( (WaveHeader[bufnum]->dwFlags & WHDR_DONE) != 0); - bufnum++, bufnum &= BX_SOUND_WINDOWS_NMASK) - { - WRITELOG( WAVELOG(5), "Buffer %d done.", bufnum); - - ret = waveOutUnprepareHeader(WaveOut, WaveHeader[bufnum], sizeof(*WaveHeader[bufnum])); - } - - tailfull = bufnum; - - // enable gathering data if a buffer is available - if ( ( (head + 2) & BX_SOUND_WINDOWS_NMASK) != tailfull ) - { - WRITELOG( WAVELOG(5), "Buffer status: Head %d, TailFull %d, TailPlay %d. Ready.", - head, tailfull, tailplay); - iswaveready = 1; - } -} - -#endif // defined(WIN32) diff --git a/tools/ioemu/iodev/soundwin.h b/tools/ioemu/iodev/soundwin.h deleted file mode 100644 index 122fa554e9..0000000000 --- a/tools/ioemu/iodev/soundwin.h +++ /dev/null @@ -1,229 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: soundwin.h,v 1.3 2001/10/03 13:10:38 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -// This file (SOUNDWIN.H) written and donated by Josef Drexler - - -#if defined(WIN32) - -#include "bochs.h" -#include - -// uncomment one of the following two #defines -//#define usesndPlaySnd -#define usewaveOut - -#define BX_SOUND_WINDOWS_MAXSYSEXLEN 256 // maximum supported length of a sysex message - -#define BX_SOUND_WINDOWS_NBUF 4 // number of buffers for the output, must be power of 2 and >= 4 -#define BX_SOUND_WINDOWS_NMASK (BX_SOUND_WINDOWS_NBUF - 1) - -#ifndef WAVEMAPPER -#define WAVEMAPPER -1 -#endif - -// Definitions for WINMM.DLL, if not defined already -#ifndef MMSYSERR_NOERROR - -#pragma pack(1) - -typedef UINT HMIDIOUT; -typedef HMIDIOUT *LPHMIDIOUT; -typedef struct midihdr_tag { - LPSTR lpData; - DWORD dwBufferLength; - DWORD dwBytesRecorded; - DWORD dwUser; - DWORD dwFlags; - struct midihdr_tag *lpNext; - DWORD reserved; -} MIDIHDR, *LPMIDIHDR; - -typedef UINT HWAVEOUT; -typedef HWAVEOUT *LPHWAVEOUT; - -typedef struct wavehdr_tag { - LPSTR lpData; - DWORD dwBufferLength; - DWORD dwBytesRecorded; - DWORD dwUser; - DWORD dwFlags; - DWORD dwLoops; - struct wavehdr_tag *lpNext; - DWORD reserved; -} WAVEHDR, *LPWAVEHDR; - -#define WHDR_DONE 0x00000001 -#define WHDR_PREPARED 0x00000002 -#define WHDR_BEGINLOOP 0x00000004 -#define WHDR_ENDLOOP 0x00000008 -#define WHDR_INQUEUE 0x00000010 - - -typedef struct waveformat_tag { - WORD wFormatTag; - WORD nChannels; - DWORD nSamplesPerSec; - DWORD nAvgBytesPerSec; - WORD nBlockAlign; -} WAVEFORMAT, *LPWAVEFORMAT; - -#define WAVE_FORMAT_PCM 1 - -typedef struct pcmwaveformat_tag { - WAVEFORMAT wf; - WORD wBitsPerSample; -} PCMWAVEFORMAT, *LPPCMWAVEFORMAT; - -#define MIDIMAPPER -1 - -#define CALLBACK_NULL 0x00000000 -#define CALLBACK_WINDOW 0x00010000 -#define CALLBACK_TASK 0x00020000 -#define CALLBACK_FUNCTION 0x00030000 - -#define MMSYSERR_NOERROR 0 -#define MMSYSERR_ERROR 1 -#define MMSYSERR_BADDEVICEID 2 -#define MMSYSERR_NOTENABLED 3 -#define MMSYSERR_ALLOCATED 4 -#define MMSYSERR_INVALHANDLE 5 -#define MMSYSERR_NODRIVER 6 -#define MMSYSERR_NOMEM 7 -#define MMSYSERR_NOTSUPPORTED 8 -#define MMSYSERR_NOMAP 7 - -#define MIDIERR_UNPREPARED 64 -#define MIDIERR_STILLPLAYING 65 -#define MIDIERR_NOTREADY 66 -#define MIDIERR_NODEVICE 67 - -#define WAVERR_BADFORMAT 32 -#define WAVERR_STILLPLAYING 33 -#define WAVERR_UNPREPARED 34 -#define WAVERR_SYNC 35 - -#define MAXERRORLENGTH 128 - -extern "C" { -UINT STDCALL midiOutOpen(LPHMIDIOUT, UINT, DWORD, DWORD, DWORD); -UINT STDCALL midiOutShortMsg(HMIDIOUT, DWORD); -UINT STDCALL midiOutLongMsg(HMIDIOUT, LPMIDIHDR, UINT); -UINT STDCALL midiOutPrepareHeader(HMIDIOUT, LPMIDIHDR, UINT); -UINT STDCALL midiOutUnprepareHeader(HMIDIOUT, LPMIDIHDR, UINT); -UINT STDCALL midiOutReset(HMIDIOUT); -UINT STDCALL midiOutClose(HMIDIOUT); - -UINT STDCALL waveOutOpen(LPHWAVEOUT, UINT, LPWAVEFORMAT, DWORD, DWORD, DWORD); -UINT STDCALL waveOutWrite(HWAVEOUT, LPWAVEHDR, UINT); -UINT STDCALL waveOutPrepareHeader(HWAVEOUT, LPWAVEHDR, UINT); -UINT STDCALL waveOutUnprepareHeader(HWAVEOUT, LPWAVEHDR, UINT); -UINT STDCALL waveOutReset(HWAVEOUT); -UINT STDCALL waveOutClose(HWAVEOUT); - -UINT STDCALL waveOutGetErrorTextA(UINT, LPSTR, UINT); - -BOOL STDCALL sndPlaySoundA(LPCSTR, UINT); -} - -typedef struct { - char RIFF[4]; - Bit32u length; - char TYPE[4]; - char chnk[4]; - Bit32u chnklen; - PCMWAVEFORMAT waveformat; - char chnk2[4]; - Bit32u chnk2len; - char data[1]; -} WAVEFILEHEADER, *LPWAVEFILEHEADER; -#pragma pack(0) - -#endif // MMSYSERR_NOERROR defined - -class bx_sound_windows_c : public bx_sound_output_c { -public: - bx_sound_windows_c(bx_sb16_c *sb16); - BX_SOUND_VIRTUAL ~bx_sound_windows_c(); - - // if virtual functions are used, we have to override them - // and define our own. Otherwise this file will just implement - // the original functions -#ifdef BX_USE_SOUND_VIRTUAL - BX_SOUND_VIRTUAL int waveready(); - BX_SOUND_VIRTUAL int midiready(); - - BX_SOUND_VIRTUAL int openmidioutput(char *device); - BX_SOUND_VIRTUAL int sendmidicommand(int delta, int command, int length, Bit8u data[]); - BX_SOUND_VIRTUAL int closemidioutput(); - - BX_SOUND_VIRTUAL int openwaveoutput(char *device); - BX_SOUND_VIRTUAL int startwaveplayback(int frequency, int bits, int stereo, int format); - BX_SOUND_VIRTUAL int sendwavepacket(int length, Bit8u data[]); - BX_SOUND_VIRTUAL int stopwaveplayback(); - BX_SOUND_VIRTUAL int closewaveoutput(); -#endif - -private: - bx_sb16_c *sb16; - - struct bx_sb16_waveinfo_struct { - int frequency; - int bits; - int stereo; - int format; - }; - - HMIDIOUT MidiOut; // Midi output device - int MidiOpen; // is it open? - HWAVEOUT WaveOut; // Wave output device - int WaveOpen; // is it open? - - UINT WaveDevice; // Wave device ID, for waveOutOpen - - // some data for the wave buffers - HANDLE DataHandle; // returned by GlobalAlloc() - Bit8u *DataPointer; // returned by GlobalLock() - - LPWAVEHDR WaveHeader[BX_SOUND_WINDOWS_NBUF]; - LPSTR WaveData[BX_SOUND_WINDOWS_NBUF]; - int length[BX_SOUND_WINDOWS_NBUF]; // length of the data in the buffer - int needreopen; // if the format has changed - int head,tailfull,tailplay; // These are for three states of the buffers: empty, full, played - bx_sb16_waveinfo_struct WaveInfo; // format for the next buffer to be played - int iswaveready; - - // and the midi buffer for the SYSEX messages - LPMIDIHDR MidiHeader; - LPSTR MidiData; - int ismidiready; - - int playnextbuffer(); - void checkmidiready(); - void checkwaveready(); -}; - -#endif // defined(WIN32) diff --git a/tools/ioemu/iodev/state_file.cc b/tools/ioemu/iodev/state_file.cc deleted file mode 100644 index f7d0d0feef..0000000000 --- a/tools/ioemu/iodev/state_file.cc +++ /dev/null @@ -1,136 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: state_file.cc,v 1.9 2001/12/21 19:33:18 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - -// Classes for helping to make checkpoints of the emulator state. - - - -#include "bochs.h" -#define LOG_THIS log-> - - - -FILE *state_file::get_handle() -{ - BX_INFO(("state_file::get_handle()")); - return NULL; -} - -void state_file::write(Bit8u) -{ - BX_PANIC(("state_file::write(Bit8u)")); -} - -void state_file::write(Bit16u) -{ - BX_PANIC(("state_file::write(Bit16u)")); -} - -void state_file::write(Bit32u) -{ - BX_PANIC(("state_file::write(Bit32u)")); -} - -void state_file::write(Bit64u) -{ - BX_PANIC(("state_file::write(Bit64u)")); -} - -void state_file::write(const void *, size_t) -{ - BX_PANIC(("state_file::write(const void *, size_t)")); -} - -void state_file::read(Bit8u &) -{ - BX_PANIC(("state_file::read(uint8 &)")); -} - -void state_file::read(Bit16u &) -{ - BX_PANIC(("state_file::read(uint16 &)")); -} - -void state_file::read(Bit32u &) -{ - BX_PANIC(("state_file::read(uint32 &)")); -} - -void state_file::read(Bit64u &) -{ - BX_PANIC(("state_file::read(uint64 &)")); -} - -void state_file::read(void *, size_t) -{ - BX_PANIC(("state_file::read(void *, size_t)")); -} - -void state_file::write_check(const char *) -{ - BX_PANIC(("state_file::write_check()")); -} - -void state_file::read_check (const char *) -{ - BX_PANIC(("state_file::read_check()")); -} - -void -state_file::init(void) -{ - log = new class logfunctions(); - log->put("STAT"); - log->settype(GENLOG); -} - - -state_file::state_file (const char *name, const char *options) -{ - UNUSED(name); - UNUSED(options); - init(); - BX_DEBUG(( "Init(const char *, const char *)." )); -} - -state_file::state_file (FILE *f) -{ - UNUSED(f); - init(); - BX_INFO(("Init(FILE *).")); -} - -state_file::~state_file() -{ - BX_DEBUG(("Exit.")); - if ( log != NULL ) - { - delete log; - log = NULL; - } -} diff --git a/tools/ioemu/iodev/unmapped.cc b/tools/ioemu/iodev/unmapped.cc deleted file mode 100644 index 5c7aafedb1..0000000000 --- a/tools/ioemu/iodev/unmapped.cc +++ /dev/null @@ -1,305 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: unmapped.cc,v 1.22 2003/08/10 17:19:49 akrisak Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" - -#define LOG_THIS theUnmappedDevice-> - - -bx_unmapped_c *theUnmappedDevice = NULL; - - int -libunmapped_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - theUnmappedDevice = new bx_unmapped_c (); - bx_devices.pluginUnmapped = theUnmappedDevice; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theUnmappedDevice, BX_PLUGIN_UNMAPPED); - return(0); // Success -} - - void -libunmapped_LTX_plugin_fini(void) -{ -} - -bx_unmapped_c::bx_unmapped_c(void) -{ - put("UNMP"); - settype(UNMAPLOG); - s.port80 = 0x00; - s.port8e = 0x00; - s.shutdown = 0; -} - -bx_unmapped_c::~bx_unmapped_c(void) -{ - // Nothing yet -} - - void -bx_unmapped_c::init(void) -{ - DEV_register_default_ioread_handler(this, read_handler, "Unmapped", 7); - DEV_register_default_iowrite_handler(this, write_handler, "Unmapped", 7); -} - - void -bx_unmapped_c::reset(unsigned type) -{ -} - - // static IO port read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_unmapped_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_UM_SMF - bx_unmapped_c *class_ptr = (bx_unmapped_c *) this_ptr; - - return( class_ptr->read(address, io_len) ); -} - - Bit32u -bx_unmapped_c::read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_UM_SMF - UNUSED(io_len); - - Bit32u retval; - - // This function gets called for access to any IO ports which - // are not mapped to any device handler. Reads return 0 - - if (address >= 0x02e0 && address <= 0x02ef) { - retval = 0; - goto return_from_read; - } - - switch (address) { - case 0x80: - retval = BX_UM_THIS s.port80; - break; - case 0x8e: - retval = BX_UM_THIS s.port8e; - break; -#if BX_PORT_E9_HACK - // Unused port on ISA - this can be used by the emulated code - // to detect it is running inside Bochs and that the debugging - // features are available (write 0xFF or something on unused - // port 0x80, then read from 0xe9, if value is 0xe9, debug - // output is available) (see write() for that) -- Andreas and Emmanuel - case 0xe9: - retval = 0xe9; - break; -#endif - case 0x03df: - retval = 0xffffffff; - BX_DEBUG(("unsupported IO read from port %04x (CGA)", address)); - break; - case 0x023a: - case 0x02f8: /* UART */ - case 0x02f9: /* UART */ - case 0x02fb: /* UART */ - case 0x02fc: /* UART */ - case 0x02fd: /* UART */ - case 0x02ea: - case 0x02eb: - case 0x03e8: - case 0x03e9: - case 0x03ea: - case 0x03eb: - case 0x03ec: - case 0x03ed: - case 0x03f8: /* UART */ - case 0x03f9: /* UART */ - case 0x03fb: /* UART */ - case 0x03fc: /* UART */ - case 0x03fd: /* UART */ - case 0x17c6: - retval = 0xffffffff; - BX_DEBUG(("unsupported IO read from port %04x", address)); - break; - default: - retval = 0xffffffff; - } - - return_from_read: - if (bx_dbg.unsupported_io) - switch (io_len) { - case 1: - retval = (Bit8u)retval; - BX_DEBUG(("unmapped: 8-bit read from %04x = %02x", address, retval)); - break; - case 2: - retval = (Bit16u)retval; - BX_DEBUG(("unmapped: 16-bit read from %04x = %04x", address, retval)); - break; - case 4: - BX_DEBUG(("unmapped: 32-bit read from %04x = %08x", address, retval)); - break; - default: - BX_DEBUG(("unmapped: %d-bit read from %04x = %x", io_len * 8, address, retval)); - } - return retval; -} - - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_unmapped_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_UM_SMF - bx_unmapped_c *class_ptr = (bx_unmapped_c *) this_ptr; - - class_ptr->write(address, value, io_len); -} - - void -bx_unmapped_c::write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_UM_SMF - UNUSED(io_len); - - - // This function gets called for access to any IO ports which - // are not mapped to any device handler. Writes to an unmapped - // IO port are ignored. - -// ??? - - if (address >= 0x02e0 && address <= 0x02ef) - goto return_from_write; - - switch (address) { - case 0x80: // diagnostic test port to display progress of POST - //BX_DEBUG(("Diagnostic port 80h: write = %02xh", (unsigned) value)); - BX_UM_THIS s.port80 = value; - break; - - case 0x8e: // ??? - BX_UM_THIS s.port8e = value; - break; - -#if BX_PORT_E9_HACK - // This port doesn't exist on normal ISA architecture. However, - // we define a convention here, to display on the console of the - // system running Bochs, anything that is written to it. The - // idea is to provide debug output very early when writing - // BIOS or OS code for example, without having to bother with - // properly setting up a serial port or anything. - // - // Idea by Andreas Beck (andreas.beck@ggi-project.org) - - case 0xe9: - putchar(value); - fflush(stdout); - break; -#endif - - case 0xed: // Dummy port used as I/O delay - break; - case 0xee: // ??? - break; - - case 0x2f2: - case 0x2f3: - case 0x2f4: - case 0x2f5: - case 0x2f6: - case 0x2f7: - case 0x3e8: - case 0x3e9: - case 0x3eb: - case 0x3ec: - case 0x3ed: - // BX_DEBUG(("unsupported IO write to port %04x of %02x", - // address, value)); - break; - - case 0x8900: // Shutdown port, could be moved in a PM device - // or a host <-> guest communication device - switch (value) { - case 'S': if (BX_UM_THIS s.shutdown == 0) BX_UM_THIS s.shutdown = 1; break; - case 'h': if (BX_UM_THIS s.shutdown == 1) BX_UM_THIS s.shutdown = 2; break; - case 'u': if (BX_UM_THIS s.shutdown == 2) BX_UM_THIS s.shutdown = 3; break; - case 't': if (BX_UM_THIS s.shutdown == 3) BX_UM_THIS s.shutdown = 4; break; - case 'd': if (BX_UM_THIS s.shutdown == 4) BX_UM_THIS s.shutdown = 5; break; - case 'o': if (BX_UM_THIS s.shutdown == 5) BX_UM_THIS s.shutdown = 6; break; - case 'w': if (BX_UM_THIS s.shutdown == 6) BX_UM_THIS s.shutdown = 7; break; - case 'n': if (BX_UM_THIS s.shutdown == 7) BX_UM_THIS s.shutdown = 8; break; -#if BX_DEBUGGER - // Very handy for debugging: - // output 'D' to port 8900, and bochs quits to debugger - case 'D': bx_debug_break (); break; -#endif - default : BX_UM_THIS s.shutdown = 0; break; - } - if (BX_UM_THIS s.shutdown == 8) { - bx_user_quit = 1; - LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL); - BX_PANIC(("Shutdown port: shutdown requested")); - } - break; - - case 0xfedc: - bx_dbg.debugger = (value > 0); - BX_DEBUG(( "DEBUGGER = %u", (unsigned) bx_dbg.debugger)); - break; - - default: - break; - } - return_from_write: - if (bx_dbg.unsupported_io) - switch (io_len) { - case 1: - BX_INFO(("unmapped: 8-bit write to %04x = %02x", address, value)); - break; - case 2: - BX_INFO(("unmapped: 16-bit write to %04x = %04x", address, value)); - break; - case 4: - BX_INFO(("unmapped: 32-bit write to %04x = %08x", address, value)); - break; - default: - BX_INFO(("unmapped: %d-bit write to %04x = %x", io_len * 8, address, value)); - break; - } -} diff --git a/tools/ioemu/iodev/unmapped.h b/tools/ioemu/iodev/unmapped.h deleted file mode 100644 index c9ef1dc068..0000000000 --- a/tools/ioemu/iodev/unmapped.h +++ /dev/null @@ -1,64 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: unmapped.h,v 1.10 2002/10/24 21:07:52 bdenney Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - - -#if BX_USE_UM_SMF -# define BX_UM_SMF static -# define BX_UM_THIS theUnmappedDevice-> -#else -# define BX_UM_SMF -# define BX_UM_THIS this-> -#endif - - - -class bx_unmapped_c : public bx_devmodel_c { -public: - bx_unmapped_c(void); - ~bx_unmapped_c(void); - - virtual void init(void); - virtual void reset (unsigned type); - -private: - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); -#if !BX_USE_UM_SMF - Bit32u read(Bit32u address, unsigned io_len); - void write(Bit32u address, Bit32u value, unsigned io_len); -#endif - - - struct { - Bit8u port80; - Bit8u port8e; - Bit8u shutdown; - } s; // state information - - }; diff --git a/tools/ioemu/iodev/vga.cc b/tools/ioemu/iodev/vga.cc deleted file mode 100644 index 894f80bbb6..0000000000 --- a/tools/ioemu/iodev/vga.cc +++ /dev/null @@ -1,3116 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: vga.cc,v 1.94.2.1 2004/02/02 22:37:48 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - -// Define BX_PLUGGABLE in files that can be compiled into plugins. For -// platforms that require a special tag on exported symbols, BX_PLUGGABLE -// is used to know when we are exporting symbols and when we are importing. -#define BX_PLUGGABLE - -#include "bochs.h" - -#define LOG_THIS theVga-> - -/* NOTES: - * I take it data rotate is a true rotate with carry of bit 0 to bit 7. - * support map mask (3c5 reg 02) - */ - -/* Notes from cb - * - * It seems that the vga card should support multi bytes IO reads and write - * From my tests, inw(port) return port+1 * 256 + port, except for port 0x3c9 - * (PEL data register, data cycling). More reverse engineering is needed. - * This would fix the gentoo bug. - */ - -// (mch) -#define VGA_TRACE_FEATURE - -// Only reference the array if the tile numbers are within the bounds -// of the array. If out of bounds, do nothing. -#define SET_TILE_UPDATED(xtile,ytile,value) \ - do { \ - if (((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES)) \ - BX_VGA_THIS s.vga_tile_updated[(xtile)][(ytile)] = value; \ - } while (0) - -// Only reference the array if the tile numbers are within the bounds -// of the array. If out of bounds, return 0. -#define GET_TILE_UPDATED(xtile,ytile) \ - ((((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES))? \ - BX_VGA_THIS s.vga_tile_updated[(xtile)][(ytile)] \ - : 0) - -static const Bit8u ccdat[16][4] = { - { 0x00, 0x00, 0x00, 0x00 }, - { 0xff, 0x00, 0x00, 0x00 }, - { 0x00, 0xff, 0x00, 0x00 }, - { 0xff, 0xff, 0x00, 0x00 }, - { 0x00, 0x00, 0xff, 0x00 }, - { 0xff, 0x00, 0xff, 0x00 }, - { 0x00, 0xff, 0xff, 0x00 }, - { 0xff, 0xff, 0xff, 0x00 }, - { 0x00, 0x00, 0x00, 0xff }, - { 0xff, 0x00, 0x00, 0xff }, - { 0x00, 0xff, 0x00, 0xff }, - { 0xff, 0xff, 0x00, 0xff }, - { 0x00, 0x00, 0xff, 0xff }, - { 0xff, 0x00, 0xff, 0xff }, - { 0x00, 0xff, 0xff, 0xff }, - { 0xff, 0xff, 0xff, 0xff }, -}; - -bx_vga_c *theVga = NULL; - -unsigned old_iHeight = 0, old_iWidth = 0, old_MSL = 0, old_BPP = 0; - - int -libvga_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) -{ - theVga = new bx_vga_c (); - bx_devices.pluginVgaDevice = theVga; - BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theVga, BX_PLUGIN_VGA); - return(0); // Success -} - - void -libvga_LTX_plugin_fini(void) -{ -} - -bx_vga_c::bx_vga_c(void) -{ - put("VGA"); - s.vga_mem_updated = 0; - s.x_tilesize = X_TILESIZE; - s.y_tilesize = Y_TILESIZE; - timer_id = BX_NULL_TIMER_HANDLE; -} - - -bx_vga_c::~bx_vga_c(void) -{ - // nothing for now -} - - - void -bx_vga_c::init(void) -{ - unsigned i; - unsigned x,y; - - unsigned addr; - for (addr=0x03B4; addr<=0x03B5; addr++) { - DEV_register_ioread_handler(this, read_handler, addr, "vga video", 1); - DEV_register_iowrite_handler(this, write_handler, addr, "vga video", 3); - } - - for (addr=0x03BA; addr<=0x03BA; addr++) { - DEV_register_ioread_handler(this, read_handler, addr, "vga video", 1); - DEV_register_iowrite_handler(this, write_handler, addr, "vga video", 3); - } - - for (addr=0x03C0; addr<=0x03CF; addr++) { - DEV_register_ioread_handler(this, read_handler, addr, "vga video", 1); - DEV_register_iowrite_handler(this, write_handler, addr, "vga video", 3); - } - - for (addr=0x03D4; addr<=0x03D5; addr++) { - DEV_register_ioread_handler(this, read_handler, addr, "vga video", 1); - DEV_register_iowrite_handler(this, write_handler, addr, "vga video", 3); - } - - for (addr=0x03DA; addr<=0x03DA; addr++) { - DEV_register_ioread_handler(this, read_handler, addr, "vga video", 1); - DEV_register_iowrite_handler(this, write_handler, addr, "vga video", 3); - } - - - BX_VGA_THIS s.misc_output.color_emulation = 1; - BX_VGA_THIS s.misc_output.enable_ram = 1; - BX_VGA_THIS s.misc_output.clock_select = 0; - BX_VGA_THIS s.misc_output.select_high_bank = 0; - BX_VGA_THIS s.misc_output.horiz_sync_pol = 1; - BX_VGA_THIS s.misc_output.vert_sync_pol = 1; - - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha = 0; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type = 0; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics = 1; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity = 0; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat = 0; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select = 0; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size = 0; - - BX_VGA_THIS s.line_offset=80; - BX_VGA_THIS s.line_compare=1023; - BX_VGA_THIS s.vertical_display_end=399; - - for (i=0; i<=0x18; i++) - BX_VGA_THIS s.CRTC.reg[i] = 0; - BX_VGA_THIS s.CRTC.address = 0; - - BX_VGA_THIS s.attribute_ctrl.flip_flop = 0; - BX_VGA_THIS s.attribute_ctrl.address = 0; - BX_VGA_THIS s.attribute_ctrl.video_enabled = 1; - for (i=0; i<16; i++) - BX_VGA_THIS s.attribute_ctrl.palette_reg[i] = 0; - BX_VGA_THIS s.attribute_ctrl.overscan_color = 0; - BX_VGA_THIS s.attribute_ctrl.color_plane_enable = 0x0f; - BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning = 0; - BX_VGA_THIS s.attribute_ctrl.color_select = 0; - - for (i=0; i<256; i++) { - BX_VGA_THIS s.pel.data[i].red = 0; - BX_VGA_THIS s.pel.data[i].green = 0; - BX_VGA_THIS s.pel.data[i].blue = 0; - } - BX_VGA_THIS s.pel.write_data_register = 0; - BX_VGA_THIS s.pel.write_data_cycle = 0; - BX_VGA_THIS s.pel.read_data_register = 0; - BX_VGA_THIS s.pel.read_data_cycle = 0; - BX_VGA_THIS s.pel.dac_state = 0x01; - BX_VGA_THIS s.pel.mask = 0xff; - - BX_VGA_THIS s.graphics_ctrl.index = 0; - BX_VGA_THIS s.graphics_ctrl.set_reset = 0; - BX_VGA_THIS s.graphics_ctrl.enable_set_reset = 0; - BX_VGA_THIS s.graphics_ctrl.color_compare = 0; - BX_VGA_THIS s.graphics_ctrl.data_rotate = 0; - BX_VGA_THIS s.graphics_ctrl.raster_op = 0; - BX_VGA_THIS s.graphics_ctrl.read_map_select = 0; - BX_VGA_THIS s.graphics_ctrl.write_mode = 0; - BX_VGA_THIS s.graphics_ctrl.read_mode = 0; - BX_VGA_THIS s.graphics_ctrl.odd_even = 0; - BX_VGA_THIS s.graphics_ctrl.chain_odd_even = 0; - BX_VGA_THIS s.graphics_ctrl.shift_reg = 0; - BX_VGA_THIS s.graphics_ctrl.graphics_alpha = 0; - BX_VGA_THIS s.graphics_ctrl.memory_mapping = 2; // monochrome text mode - BX_VGA_THIS s.graphics_ctrl.color_dont_care = 0; - BX_VGA_THIS s.graphics_ctrl.bitmask = 0; - for (i=0; i<4; i++) { - BX_VGA_THIS s.graphics_ctrl.latch[i] = 0; - } - - BX_VGA_THIS s.sequencer.index = 0; - BX_VGA_THIS s.sequencer.map_mask = 0; - for (i=0; i<4; i++) { - BX_VGA_THIS s.sequencer.map_mask_bit[i] = 0; - } - BX_VGA_THIS s.sequencer.reset1 = 1; - BX_VGA_THIS s.sequencer.reset2 = 1; - BX_VGA_THIS s.sequencer.reg1 = 0; - BX_VGA_THIS s.sequencer.char_map_select = 0; - BX_VGA_THIS s.sequencer.extended_mem = 1; // display mem greater than 64K - BX_VGA_THIS s.sequencer.odd_even = 1; // use sequential addressing mode - BX_VGA_THIS s.sequencer.chain_four = 0; // use map mask & read map select - - memset(BX_VGA_THIS s.vga_memory, 0, sizeof(BX_VGA_THIS s.vga_memory)); - - BX_VGA_THIS s.vga_mem_updated = 0; - for (y=0; y<480/Y_TILESIZE; y++) - for (x=0; x<640/X_TILESIZE; x++) - SET_TILE_UPDATED (x, y, 0); - - { - /* ??? should redo this to pass X args */ - char *argv[1] = { "bochs" }; - bx_gui->init(1, &argv[0], BX_VGA_THIS s.x_tilesize, BX_VGA_THIS s.y_tilesize); - } - - BX_INFO(("interval=%u", bx_options.Ovga_update_interval->get ())); - if (BX_VGA_THIS timer_id == BX_NULL_TIMER_HANDLE) { - BX_VGA_THIS timer_id = bx_pc_system.register_timer(this, timer_handler, - bx_options.Ovga_update_interval->get (), 1, 1, "vga"); - } - - /* video card with BIOS ROM */ - DEV_cmos_set_reg(0x14, (DEV_cmos_get_reg(0x14) & 0xcf) | 0x00); - - BX_VGA_THIS s.charmap_address = 0; - BX_VGA_THIS s.x_dotclockdiv2 = 0; - BX_VGA_THIS s.y_doublescan = 0; - -#if BX_SUPPORT_VBE - // The following is for the vbe display extension - - for (addr=VBE_DISPI_IOPORT_INDEX; addr<=VBE_DISPI_IOPORT_DATA; addr++) { - DEV_register_ioread_handler(this, vbe_read_handler, addr, "vga video", 7); - DEV_register_iowrite_handler(this, vbe_write_handler, addr, "vga video", 7); - } -#if !BX_PCI_USB_SUPPORT - for (addr=VBE_DISPI_IOPORT_INDEX_OLD; addr<=VBE_DISPI_IOPORT_DATA_OLD; addr++) { - DEV_register_ioread_handler(this, vbe_read_handler, addr, "vga video", 7); - DEV_register_iowrite_handler(this, vbe_write_handler, addr, "vga video", 7); - } -#endif - BX_VGA_THIS s.vbe_cur_dispi=VBE_DISPI_ID0; - BX_VGA_THIS s.vbe_xres=640; - BX_VGA_THIS s.vbe_yres=480; - BX_VGA_THIS s.vbe_bpp=8; - BX_VGA_THIS s.vbe_bank=0; - BX_VGA_THIS s.vbe_enabled=0; - BX_VGA_THIS s.vbe_curindex=0; - BX_VGA_THIS s.vbe_offset_x=0; - BX_VGA_THIS s.vbe_offset_y=0; - BX_VGA_THIS s.vbe_virtual_xres=640; - BX_VGA_THIS s.vbe_virtual_yres=480; - BX_VGA_THIS s.vbe_bpp_multiplier=1; - BX_VGA_THIS s.vbe_virtual_start=0; - BX_VGA_THIS s.vbe_line_byte_width=640; - BX_VGA_THIS s.vbe_lfb_enabled=0; - - - BX_INFO(("VBE Bochs Display Extension Enabled")); -#endif - bios_init(); -} - - void -bx_vga_c::bios_init() -{ - int i; - - BX_VGA_THIS s.misc_output.color_emulation = 1; - BX_VGA_THIS s.misc_output.enable_ram = 1; - BX_VGA_THIS s.misc_output.clock_select = 1; - BX_VGA_THIS s.misc_output.select_high_bank = 1; - BX_VGA_THIS s.misc_output.horiz_sync_pol = 1; - BX_VGA_THIS s.misc_output.vert_sync_pol = 0; - BX_VGA_THIS s.CRTC.address = 15; - BX_VGA_THIS s.CRTC.reg[0] = 95; - BX_VGA_THIS s.CRTC.reg[1] = 79; - BX_VGA_THIS s.CRTC.reg[2] = 80; - BX_VGA_THIS s.CRTC.reg[3] = 130; - BX_VGA_THIS s.CRTC.reg[4] = 85; - BX_VGA_THIS s.CRTC.reg[5] = 129; - BX_VGA_THIS s.CRTC.reg[6] = 191; - BX_VGA_THIS s.CRTC.reg[7] = 31; - BX_VGA_THIS s.CRTC.reg[8] = 0; - BX_VGA_THIS s.CRTC.reg[9] = 79; - BX_VGA_THIS s.CRTC.reg[10] = 14; - BX_VGA_THIS s.CRTC.reg[11] = 15; - BX_VGA_THIS s.CRTC.reg[12] = 0; - BX_VGA_THIS s.CRTC.reg[13] = 0; - BX_VGA_THIS s.CRTC.reg[14] = 5; - BX_VGA_THIS s.CRTC.reg[15] = 160; - BX_VGA_THIS s.CRTC.reg[16] = 156; - BX_VGA_THIS s.CRTC.reg[17] = 142; - BX_VGA_THIS s.CRTC.reg[18] = 143; - BX_VGA_THIS s.CRTC.reg[19] = 40; - BX_VGA_THIS s.CRTC.reg[20] = 31; - BX_VGA_THIS s.CRTC.reg[21] = 150; - BX_VGA_THIS s.CRTC.reg[22] = 185; - BX_VGA_THIS s.CRTC.reg[23] = 163; - BX_VGA_THIS s.CRTC.reg[24] = 255; - BX_VGA_THIS s.attribute_ctrl.flip_flop = 1; - BX_VGA_THIS s.attribute_ctrl.address = 0; - BX_VGA_THIS s.attribute_ctrl.video_enabled = 1; - BX_VGA_THIS s.attribute_ctrl.palette_reg[0] = 0; - BX_VGA_THIS s.attribute_ctrl.palette_reg[1] = 1; - BX_VGA_THIS s.attribute_ctrl.palette_reg[2] = 2; - BX_VGA_THIS s.attribute_ctrl.palette_reg[3] = 3; - BX_VGA_THIS s.attribute_ctrl.palette_reg[4] = 4; - BX_VGA_THIS s.attribute_ctrl.palette_reg[5] = 5; - BX_VGA_THIS s.attribute_ctrl.palette_reg[6] = 6; - BX_VGA_THIS s.attribute_ctrl.palette_reg[7] = 7; - BX_VGA_THIS s.attribute_ctrl.palette_reg[8] = 8; - BX_VGA_THIS s.attribute_ctrl.palette_reg[9] = 9; - BX_VGA_THIS s.attribute_ctrl.palette_reg[10] = 10; - BX_VGA_THIS s.attribute_ctrl.palette_reg[11] = 11; - BX_VGA_THIS s.attribute_ctrl.palette_reg[12] = 12; - BX_VGA_THIS s.attribute_ctrl.palette_reg[13] = 13; - BX_VGA_THIS s.attribute_ctrl.palette_reg[14] = 14; - BX_VGA_THIS s.attribute_ctrl.palette_reg[15] = 15; - BX_VGA_THIS s.attribute_ctrl.overscan_color = 0; - BX_VGA_THIS s.attribute_ctrl.color_plane_enable = 15; - BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning = 8; - BX_VGA_THIS s.attribute_ctrl.color_select = 0; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha = 0; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type = 0; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics = 1; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity = 1; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat = 0; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select = 0; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size = 0; - BX_VGA_THIS s.pel.write_data_register = 16; - BX_VGA_THIS s.pel.write_data_cycle = 0; - BX_VGA_THIS s.pel.read_data_register = 0; - BX_VGA_THIS s.pel.read_data_cycle = 0; - BX_VGA_THIS s.pel.dac_state = 0; - memset((BX_VGA_THIS s.pel.data), 0, 256); - BX_VGA_THIS s.pel.data[0].red = 0; - BX_VGA_THIS s.pel.data[0].green = 0; - BX_VGA_THIS s.pel.data[0].blue = 0; - BX_VGA_THIS s.pel.mask = 255; - BX_VGA_THIS s.graphics_ctrl.index = 6; - BX_VGA_THIS s.graphics_ctrl.set_reset = 0; - BX_VGA_THIS s.graphics_ctrl.enable_set_reset = 0; - BX_VGA_THIS s.graphics_ctrl.color_compare = 0; - BX_VGA_THIS s.graphics_ctrl.data_rotate = 0; - BX_VGA_THIS s.graphics_ctrl.raster_op = 0; - BX_VGA_THIS s.graphics_ctrl.read_map_select = 0; - BX_VGA_THIS s.graphics_ctrl.write_mode = 0; - BX_VGA_THIS s.graphics_ctrl.read_mode = 0; - BX_VGA_THIS s.graphics_ctrl.odd_even = 1; - BX_VGA_THIS s.graphics_ctrl.chain_odd_even = 1; - BX_VGA_THIS s.graphics_ctrl.shift_reg = 0; - BX_VGA_THIS s.graphics_ctrl.graphics_alpha = 0; - BX_VGA_THIS s.graphics_ctrl.memory_mapping = 3; - BX_VGA_THIS s.graphics_ctrl.color_dont_care = 15; - BX_VGA_THIS s.graphics_ctrl.bitmask = 255; - BX_VGA_THIS s.graphics_ctrl.latch[0] = 0; - BX_VGA_THIS s.graphics_ctrl.latch[1] = 0; - BX_VGA_THIS s.graphics_ctrl.latch[2] = 0; - BX_VGA_THIS s.graphics_ctrl.latch[3] = 0; - BX_VGA_THIS s.sequencer.index = 3; - BX_VGA_THIS s.sequencer.map_mask = 3; - BX_VGA_THIS s.sequencer.map_mask_bit[0] = 1; - BX_VGA_THIS s.sequencer.map_mask_bit[1] = 1; - BX_VGA_THIS s.sequencer.map_mask_bit[2] = 0; - BX_VGA_THIS s.sequencer.map_mask_bit[3] = 0; - BX_VGA_THIS s.sequencer.reset1 = 1; - BX_VGA_THIS s.sequencer.reset2 = 1; - BX_VGA_THIS s.sequencer.reg1 = 0; - BX_VGA_THIS s.sequencer.char_map_select = 0; - BX_VGA_THIS s.sequencer.extended_mem = 1; - BX_VGA_THIS s.sequencer.odd_even = 0; - BX_VGA_THIS s.sequencer.chain_four = 0; - BX_VGA_THIS s.vga_mem_updated = 1; - BX_VGA_THIS s.x_tilesize = 16; - BX_VGA_THIS s.y_tilesize = 24; - BX_VGA_THIS s.line_offset = 160; - BX_VGA_THIS s.line_compare = 1023; - BX_VGA_THIS s.vertical_display_end = 399; - memset((BX_VGA_THIS s.vga_tile_updated), 0, BX_NUM_X_TILES * BX_NUM_Y_TILES); - - memset((BX_VGA_THIS s.vga_memory), ' ', 256 * 1024); - for(i = 0; i < 256 * 1024;i+=2) { - BX_VGA_THIS s.vga_memory[i] = ' '; - BX_VGA_THIS s.vga_memory[i+1] = 0x07; - - } - memset((BX_VGA_THIS s.text_snapshot), 0, 32 * 1024); - memset((BX_VGA_THIS s.rgb), 0, 3 * 256); - memset((BX_VGA_THIS s.tile), 0, X_TILESIZE * Y_TILESIZE * 4); - BX_VGA_THIS s.charmap_address = 0; - BX_VGA_THIS s.x_dotclockdiv2 = 0; - BX_VGA_THIS s.y_doublescan = 1; -} - - void -bx_vga_c::reset(unsigned type) -{ -} - - - void -bx_vga_c::determine_screen_dimensions(unsigned *piHeight, unsigned *piWidth) -{ - int ai[0x20]; - int i,h,v; - for ( i = 0 ; i < 0x20 ; i++ ) - ai[i] = BX_VGA_THIS s.CRTC.reg[i]; - - h = (ai[1] + 1) * 8; - v = (ai[18] | ((ai[7] & 0x02) << 7) | ((ai[7] & 0x40) << 3)) + 1; - - if ( BX_VGA_THIS s.graphics_ctrl.shift_reg == 0 ) - { - *piWidth = 640; - *piHeight = 480; - - if ( BX_VGA_THIS s.CRTC.reg[6] == 0xBF ) - { - if (BX_VGA_THIS s.CRTC.reg[23] == 0xA3 && - BX_VGA_THIS s.CRTC.reg[20] == 0x40 && - BX_VGA_THIS s.CRTC.reg[9] == 0x41) - { - *piWidth = 320; - *piHeight = 240; - } - else { - if (BX_VGA_THIS s.x_dotclockdiv2) h <<= 1; - *piWidth = h; - *piHeight = v; - } - } - else if ((h >= 640) && (v >= 480)) { - *piWidth = h; - *piHeight = v; - } - } - else if ( BX_VGA_THIS s.graphics_ctrl.shift_reg == 2 ) - { - - if ( BX_VGA_THIS s.sequencer.chain_four ) - { - *piWidth = h; - *piHeight = v; - } - else - { - *piWidth = h; - *piHeight = v; - } - } - else - { - if (BX_VGA_THIS s.x_dotclockdiv2) h <<= 1; - *piWidth = h; - *piHeight = v; - } -} - - - // static IO port read callback handler - // redirects to non-static class handler to avoid virtual functions - - Bit32u -bx_vga_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_VGA_SMF - bx_vga_c *class_ptr = (bx_vga_c *) this_ptr; - - return( class_ptr->read(address, io_len) ); -} - - - Bit32u -bx_vga_c::read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_VGA_SMF - bx_bool horiz_retrace = 0, vert_retrace = 0; - Bit64u usec; - Bit16u vertres; - Bit8u retval; - -#if defined(VGA_TRACE_FEATURE) - Bit32u ret = 0; -#define RETURN(x) do { ret = (x); goto read_return; } while (0) -#else -#define RETURN return -#endif - -#ifdef __OS2__ - if ( bx_options.videomode == BX_VIDEO_DIRECT ) - { - return _inp(address); - } -#endif - -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("io read from 0x%04x", (unsigned) address)); -#endif - - if ( (address >= 0x03b0) && (address <= 0x03bf) && - (BX_VGA_THIS s.misc_output.color_emulation) ) { - RETURN(0xff); - } - if ( (address >= 0x03d0) && (address <= 0x03df) && - (BX_VGA_THIS s.misc_output.color_emulation==0) ) { - RETURN(0xff); - } - - switch (address) { - case 0x03ba: /* Input Status 1 (monochrome emulation modes) */ - case 0x03ca: /* Feature Control ??? */ - case 0x03da: /* Input Status 1 (color emulation modes) */ - // bit3: Vertical Retrace - // 0 = display is in the display mode - // 1 = display is in the vertical retrace mode - // bit0: Display Enable - // 0 = display is in the display mode - // 1 = display is not in the display mode; either the - // horizontal or vertical retrace period is active - - // using 72 Hz vertical frequency - usec = bx_pc_system.time_usec(); - switch ( ( BX_VGA_THIS s.misc_output.vert_sync_pol << 1) | BX_VGA_THIS s.misc_output.horiz_sync_pol ) - { - case 0: vertres = 200; break; - case 1: vertres = 400; break; - case 2: vertres = 350; break; - default: vertres = 480; break; - } - if ((usec % 13888) < 70) { - vert_retrace = 1; - } - if ((usec % (13888 / vertres)) == 0) { - horiz_retrace = 1; - } - - retval = 0; - if (horiz_retrace || vert_retrace) - retval = 0x01; - if (vert_retrace) - retval |= 0x08; - - /* reading this port resets the flip-flop to address mode */ - BX_VGA_THIS s.attribute_ctrl.flip_flop = 0; - RETURN(retval); - break; - - - case 0x03c0: /* */ - if (BX_VGA_THIS s.attribute_ctrl.flip_flop == 0) { - //BX_INFO(("io read: 0x3c0: flip_flop = 0")); - retval = - (BX_VGA_THIS s.attribute_ctrl.video_enabled << 5) | - BX_VGA_THIS s.attribute_ctrl.address; - RETURN(retval); - } - else { - BX_ERROR(("io read: 0x3c0: flip_flop != 0")); - return(0); - } - break; - - case 0x03c1: /* */ - switch (BX_VGA_THIS s.attribute_ctrl.address) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - retval = BX_VGA_THIS s.attribute_ctrl.palette_reg[BX_VGA_THIS s.attribute_ctrl.address]; - RETURN(retval); - break; - case 0x10: /* mode control register */ - retval = - (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha << 0) | - (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type << 1) | - (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics << 2) | - (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity << 3) | - (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat << 5) | - (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select << 6) | - (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size << 7); - RETURN(retval); - break; - case 0x11: /* overscan color register */ - RETURN(BX_VGA_THIS s.attribute_ctrl.overscan_color); - break; - case 0x12: /* color plane enable */ - RETURN(BX_VGA_THIS s.attribute_ctrl.color_plane_enable); - break; - case 0x13: /* horizontal PEL panning register */ - RETURN(BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning); - break; - case 0x14: /* color select register */ - RETURN(BX_VGA_THIS s.attribute_ctrl.color_select); - break; - default: - BX_INFO(("io read: 0x3c1: unknown register 0x%02x", - (unsigned) BX_VGA_THIS s.attribute_ctrl.address)); - RETURN(0); - } - break; - - case 0x03c2: /* Input Status 0 */ - BX_DEBUG(("io read 0x3c2: input status #0: ignoring")); - RETURN(0); - break; - - case 0x03c3: /* VGA Enable Register */ - RETURN(1); - break; - - case 0x03c4: /* Sequencer Index Register */ - RETURN(BX_VGA_THIS s.sequencer.index); - break; - - case 0x03c5: /* Sequencer Registers 00..04 */ - switch (BX_VGA_THIS s.sequencer.index) { - case 0: /* sequencer: reset */ - BX_DEBUG(("io read 0x3c5: sequencer reset")); - RETURN(BX_VGA_THIS s.sequencer.reset1 | (BX_VGA_THIS s.sequencer.reset2<<1)); - break; - case 1: /* sequencer: clocking mode */ - BX_DEBUG(("io read 0x3c5: sequencer clocking mode")); - RETURN(BX_VGA_THIS s.sequencer.reg1); - break; - case 2: /* sequencer: map mask register */ - RETURN(BX_VGA_THIS s.sequencer.map_mask); - break; - case 3: /* sequencer: character map select register */ - RETURN(BX_VGA_THIS s.sequencer.char_map_select); - break; - case 4: /* sequencer: memory mode register */ - retval = - (BX_VGA_THIS s.sequencer.extended_mem << 1) | - (BX_VGA_THIS s.sequencer.odd_even << 2) | - (BX_VGA_THIS s.sequencer.chain_four << 3); - RETURN(retval); - break; - - default: - BX_DEBUG(("io read 0x3c5: index %u unhandled", - (unsigned) BX_VGA_THIS s.sequencer.index)); - RETURN(0); - } - break; - - case 0x03c6: /* PEL mask ??? */ - RETURN(BX_VGA_THIS s.pel.mask); - break; - - case 0x03c7: /* DAC state, read = 11b, write = 00b */ - RETURN(BX_VGA_THIS s.pel.dac_state); - break; - - case 0x03c8: /* PEL address write mode */ - RETURN(BX_VGA_THIS s.pel.write_data_register); - break; - - case 0x03c9: /* PEL Data Register, colors 00..FF */ - if (BX_VGA_THIS s.pel.dac_state == 0x03) { - switch (BX_VGA_THIS s.pel.read_data_cycle) { - case 0: - retval = BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.read_data_register].red; - break; - case 1: - retval = BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.read_data_register].green; - break; - case 2: - retval = BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.read_data_register].blue; - break; - default: - retval = 0; // keep compiler happy - } - BX_VGA_THIS s.pel.read_data_cycle++; - if (BX_VGA_THIS s.pel.read_data_cycle >= 3) { - BX_VGA_THIS s.pel.read_data_cycle = 0; - BX_VGA_THIS s.pel.read_data_register++; - } - } - else { - retval = 0x3f; - } - RETURN(retval); - break; - - case 0x03cc: /* Miscellaneous Output / Graphics 1 Position ??? */ - retval = - ((BX_VGA_THIS s.misc_output.color_emulation & 0x01) << 0) | - ((BX_VGA_THIS s.misc_output.enable_ram & 0x01) << 1) | - ((BX_VGA_THIS s.misc_output.clock_select & 0x03) << 2) | - ((BX_VGA_THIS s.misc_output.select_high_bank & 0x01) << 5) | - ((BX_VGA_THIS s.misc_output.horiz_sync_pol & 0x01) << 6) | - ((BX_VGA_THIS s.misc_output.vert_sync_pol & 0x01) << 7); - RETURN(retval); - break; - - case 0x03ce: /* Graphics Controller Index Register */ - RETURN(BX_VGA_THIS s.graphics_ctrl.index); - break; - - case 0x03cd: /* ??? */ - BX_DEBUG(("io read from 03cd")); - RETURN(0x00); - break; - - case 0x03cf: /* Graphics Controller Registers 00..08 */ - switch (BX_VGA_THIS s.graphics_ctrl.index) { - case 0: /* Set/Reset */ - RETURN(BX_VGA_THIS s.graphics_ctrl.set_reset); - break; - case 1: /* Enable Set/Reset */ - RETURN(BX_VGA_THIS s.graphics_ctrl.enable_set_reset); - break; - case 2: /* Color Compare */ - RETURN(BX_VGA_THIS s.graphics_ctrl.color_compare); - break; - case 3: /* Data Rotate */ - retval = - ((BX_VGA_THIS s.graphics_ctrl.raster_op & 0x03) << 3) | - ((BX_VGA_THIS s.graphics_ctrl.data_rotate & 0x07) << 0); - RETURN(retval); - break; - case 4: /* Read Map Select */ - RETURN(BX_VGA_THIS s.graphics_ctrl.read_map_select); - break; - case 5: /* Mode */ - retval = - ((BX_VGA_THIS s.graphics_ctrl.shift_reg & 0x03) << 5) | - ((BX_VGA_THIS s.graphics_ctrl.odd_even & 0x01 ) << 4) | - ((BX_VGA_THIS s.graphics_ctrl.read_mode & 0x01) << 3) | - ((BX_VGA_THIS s.graphics_ctrl.write_mode & 0x03) << 0); - - if (BX_VGA_THIS s.graphics_ctrl.odd_even || - BX_VGA_THIS s.graphics_ctrl.shift_reg) - BX_DEBUG(("io read 0x3cf: reg 05 = 0x%02x", (unsigned) retval)); - RETURN(retval); - break; - case 6: /* Miscellaneous */ - retval = - ((BX_VGA_THIS s.graphics_ctrl.memory_mapping & 0x03 ) << 2) | - ((BX_VGA_THIS s.graphics_ctrl.odd_even & 0x01) << 1) | - ((BX_VGA_THIS s.graphics_ctrl.graphics_alpha & 0x01) << 0); - RETURN(retval); - break; - case 7: /* Color Don't Care */ - RETURN(BX_VGA_THIS s.graphics_ctrl.color_dont_care); - break; - case 8: /* Bit Mask */ - RETURN(BX_VGA_THIS s.graphics_ctrl.bitmask); - break; - default: - /* ??? */ - BX_DEBUG(("io read: 0x3cf: index %u unhandled", - (unsigned) BX_VGA_THIS s.graphics_ctrl.index)); - RETURN(0); - } - break; - - case 0x03d4: /* CRTC Index Register (color emulation modes) */ - RETURN(BX_VGA_THIS s.CRTC.address); - break; - - case 0x03b5: /* CRTC Registers (monochrome emulation modes) */ - case 0x03d5: /* CRTC Registers (color emulation modes) */ - if (BX_VGA_THIS s.CRTC.address > 0x18) { - BX_DEBUG(("io read: invalid CRTC register 0x%02x", - (unsigned) BX_VGA_THIS s.CRTC.address)); - RETURN(0); - } - RETURN(BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address]); - break; - - case 0x03b4: /* CRTC Index Register (monochrome emulation modes) */ - case 0x03cb: /* not sure but OpenBSD reads it a lot */ - default: - BX_INFO(("io read from vga port 0x%02x", (unsigned) address)); - RETURN(0); /* keep compiler happy */ - } - -#if defined(VGA_TRACE_FEATURE) - read_return: - BX_DEBUG(("8-bit read from %04x = %02x", (unsigned) address, ret)); - return ret; -#endif -} -#if defined(VGA_TRACE_FEATURE) -#undef RETURN -#endif - - // static IO port write callback handler - // redirects to non-static class handler to avoid virtual functions - - void -bx_vga_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_VGA_SMF - bx_vga_c *class_ptr = (bx_vga_c *) this_ptr; - - class_ptr->write(address, value, io_len, 0); -#else - UNUSED(this_ptr); - theVga->write(address, value, io_len, 0); -#endif -} - - void -bx_vga_c::write_handler_no_log(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_VGA_SMF - bx_vga_c *class_ptr = (bx_vga_c *) this_ptr; - - class_ptr->write(address, value, io_len, 1); -#else - UNUSED(this_ptr); - theVga->write(address, value, io_len, 1); -#endif -} - - void -bx_vga_c::write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log) -{ - unsigned i; - Bit8u charmap1, charmap2, prev_memory_mapping; - bx_bool prev_video_enabled, prev_line_graphics, prev_int_pal_size; - bx_bool prev_graphics_alpha, prev_chain_odd_even; - bx_bool needs_update = 0; - -#if defined(VGA_TRACE_FEATURE) - if (!no_log) - switch (io_len) { - case 1: - BX_DEBUG(("8-bit write to %04x = %02x", (unsigned)address, (unsigned)value)); - break; - case 2: - BX_DEBUG(("16-bit write to %04x = %04x", (unsigned)address, (unsigned)value)); - break; - default: - BX_PANIC(("Weird VGA write size")); - } -#else - if (io_len == 1) { - BX_DEBUG(("io write to 0x%04x = 0x%02x", (unsigned) address, - (unsigned) value)); - } -#endif - - if (io_len == 2) { -#if BX_USE_VGA_SMF - bx_vga_c::write_handler_no_log(0, address, value & 0xff, 1); - bx_vga_c::write_handler_no_log(0, address+1, (value >> 8) & 0xff, 1); -#else - bx_vga_c::write(address, value & 0xff, 1, 1); - bx_vga_c::write(address+1, (value >> 8) & 0xff, 1, 1); -#endif - return; - } - -#ifdef __OS2__ - if ( bx_options.videomode == BX_VIDEO_DIRECT ) - { - _outp(address,value); - return; - } -#endif - - if ( (address >= 0x03b0) && (address <= 0x03bf) && - (BX_VGA_THIS s.misc_output.color_emulation) ) - return; - if ( (address >= 0x03d0) && (address <= 0x03df) && - (BX_VGA_THIS s.misc_output.color_emulation==0) ) - return; - - switch (address) { - case 0x03ba: /* Feature Control (monochrome emulation modes) */ -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("io write 3ba: feature control: ignoring")); -#endif - break; - - case 0x03c0: /* Attribute Controller */ - if (BX_VGA_THIS s.attribute_ctrl.flip_flop == 0) { /* address mode */ - prev_video_enabled = BX_VGA_THIS s.attribute_ctrl.video_enabled; - BX_VGA_THIS s.attribute_ctrl.video_enabled = (value >> 5) & 0x01; -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("io write 3c0: video_enabled = %u", - (unsigned) BX_VGA_THIS s.attribute_ctrl.video_enabled)); -#endif - if (BX_VGA_THIS s.attribute_ctrl.video_enabled == 0) - bx_gui->clear_screen(); - else if (!prev_video_enabled) { -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("found enable transition")); -#endif - needs_update = 1; - } - value &= 0x1f; /* address = bits 0..4 */ - BX_VGA_THIS s.attribute_ctrl.address = value; - switch (value) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - break; - - default: - BX_DEBUG(("io write 3c0: address mode reg=%u", - (unsigned) value)); - } - } - else { /* data-write mode */ - switch (BX_VGA_THIS s.attribute_ctrl.address) { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - if (value != BX_VGA_THIS s.attribute_ctrl.palette_reg[BX_VGA_THIS s.attribute_ctrl.address]) { - BX_VGA_THIS s.attribute_ctrl.palette_reg[BX_VGA_THIS s.attribute_ctrl.address] = - value; - needs_update = 1; - } - break; - case 0x10: // mode control register - prev_line_graphics = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics; - prev_int_pal_size = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha = - (value >> 0) & 0x01; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type = - (value >> 1) & 0x01; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics = - (value >> 2) & 0x01; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity = - (value >> 3) & 0x01; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat = - (value >> 5) & 0x01; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select = - (value >> 6) & 0x01; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size = - (value >> 7) & 0x01; - if (((value >> 2) & 0x01) != prev_line_graphics) { - bx_gui->set_text_charmap( - & BX_VGA_THIS s.vga_memory[0x20000 + BX_VGA_THIS s.charmap_address]); - BX_VGA_THIS s.vga_mem_updated = 1; - } - if (((value >> 7) & 0x01) != prev_int_pal_size) { - needs_update = 1; - } -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("io write 3c0: mode control: %02x h", - (unsigned) value)); -#endif - break; - case 0x11: // Overscan Color Register - BX_VGA_THIS s.attribute_ctrl.overscan_color = (value & 0x3f); -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("io write 3c0: overscan color = %02x", - (unsigned) value)); -#endif - break; - case 0x12: // Color Plane Enable Register - BX_VGA_THIS s.attribute_ctrl.color_plane_enable = (value & 0x0f); - needs_update = 1; -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("io write 3c0: color plane enable = %02x", - (unsigned) value)); -#endif - break; - case 0x13: // Horizontal Pixel Panning Register - BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning = (value & 0x0f); - needs_update = 1; -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("io write 3c0: horiz pel panning = %02x", - (unsigned) value)); -#endif - break; - case 0x14: // Color Select Register - BX_VGA_THIS s.attribute_ctrl.color_select = (value & 0x0f); - needs_update = 1; -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("io write 3c0: color select = %02x", - (unsigned) BX_VGA_THIS s.attribute_ctrl.color_select)); -#endif - break; - default: - BX_DEBUG(("io write 3c0: data-write mode %02x h", - (unsigned) BX_VGA_THIS s.attribute_ctrl.address)); - } - } - BX_VGA_THIS s.attribute_ctrl.flip_flop = !BX_VGA_THIS s.attribute_ctrl.flip_flop; - break; - - case 0x03c2: // Miscellaneous Output Register - BX_VGA_THIS s.misc_output.color_emulation = (value >> 0) & 0x01; - BX_VGA_THIS s.misc_output.enable_ram = (value >> 1) & 0x01; - BX_VGA_THIS s.misc_output.clock_select = (value >> 2) & 0x03; - BX_VGA_THIS s.misc_output.select_high_bank = (value >> 5) & 0x01; - BX_VGA_THIS s.misc_output.horiz_sync_pol = (value >> 6) & 0x01; - BX_VGA_THIS s.misc_output.vert_sync_pol = (value >> 7) & 0x01; -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("io write 3c2:")); - BX_DEBUG((" color_emulation (attempted) = %u", - (value >> 0) & 0x01)); - BX_DEBUG((" enable_ram = %u", - (unsigned) BX_VGA_THIS s.misc_output.enable_ram)); - BX_DEBUG((" clock_select = %u", - (unsigned) BX_VGA_THIS s.misc_output.clock_select)); - BX_DEBUG((" select_high_bank = %u", - (unsigned) BX_VGA_THIS s.misc_output.select_high_bank)); - BX_DEBUG((" horiz_sync_pol = %u", - (unsigned) BX_VGA_THIS s.misc_output.horiz_sync_pol)); - BX_DEBUG((" vert_sync_pol = %u", - (unsigned) BX_VGA_THIS s.misc_output.vert_sync_pol)); -#endif - break; - - case 0x03c3: // VGA enable - // bit0: enables VGA display if set -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("io write 3c3: (ignoring) VGA enable = %u", - (unsigned) (value & 0x01) )); -#endif - break; - - case 0x03c4: /* Sequencer Index Register */ - if (value > 4) { - BX_DEBUG(("io write 3c4: value > 4")); - } - BX_VGA_THIS s.sequencer.index = value; - break; - - case 0x03c5: /* Sequencer Registers 00..04 */ - switch (BX_VGA_THIS s.sequencer.index) { - case 0: /* sequencer: reset */ -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("write 0x3c5: sequencer reset: value=0x%02x", - (unsigned) value)); -#endif - if (BX_VGA_THIS s.sequencer.reset1 && ((value & 0x01) == 0)) { - BX_VGA_THIS s.sequencer.char_map_select = 0; - BX_VGA_THIS s.charmap_address = 0; - bx_gui->set_text_charmap( - & BX_VGA_THIS s.vga_memory[0x20000 + BX_VGA_THIS s.charmap_address]); - BX_VGA_THIS s.vga_mem_updated = 1; - } - BX_VGA_THIS s.sequencer.reset1 = (value >> 0) & 0x01; - BX_VGA_THIS s.sequencer.reset2 = (value >> 1) & 0x01; - break; - case 1: /* sequencer: clocking mode */ -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("io write 3c5=%02x: clocking mode reg: ignoring", - (unsigned) value)); -#endif - BX_VGA_THIS s.sequencer.reg1 = value & 0x3f; - BX_VGA_THIS s.x_dotclockdiv2 = ((value & 0x08) > 0); - break; - case 2: /* sequencer: map mask register */ - BX_VGA_THIS s.sequencer.map_mask = (value & 0x0f); - for (i=0; i<4; i++) - BX_VGA_THIS s.sequencer.map_mask_bit[i] = (value >> i) & 0x01; - break; - case 3: /* sequencer: character map select register */ - BX_VGA_THIS s.sequencer.char_map_select = value; - charmap1 = value & 0x13; - if (charmap1 > 3) charmap1 = (charmap1 & 3) + 4; - charmap2 = (value & 0x2C) >> 2; - if (charmap2 > 3) charmap2 = (charmap2 & 3) + 4; - if (BX_VGA_THIS s.CRTC.reg[0x09] > 0) { - BX_VGA_THIS s.charmap_address = (charmap1 << 13); - bx_gui->set_text_charmap( - & BX_VGA_THIS s.vga_memory[0x20000 + BX_VGA_THIS s.charmap_address]); - BX_VGA_THIS s.vga_mem_updated = 1; - } - if (charmap2 != charmap1) - BX_INFO(("char map select: #2=%d (unused)", charmap2)); - break; - case 4: /* sequencer: memory mode register */ - BX_VGA_THIS s.sequencer.extended_mem = (value >> 1) & 0x01; - BX_VGA_THIS s.sequencer.odd_even = (value >> 2) & 0x01; - BX_VGA_THIS s.sequencer.chain_four = (value >> 3) & 0x01; - -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("io write 3c5: index 4:")); - BX_DEBUG((" extended_mem %u", - (unsigned) BX_VGA_THIS s.sequencer.extended_mem)); - BX_DEBUG((" odd_even %u", - (unsigned) BX_VGA_THIS s.sequencer.odd_even)); - BX_DEBUG((" chain_four %u", - (unsigned) BX_VGA_THIS s.sequencer.chain_four)); -#endif - break; - default: - BX_DEBUG(("io write 3c5: index %u unhandled", - (unsigned) BX_VGA_THIS s.sequencer.index)); - } - break; - - case 0x03c6: /* PEL mask */ - BX_VGA_THIS s.pel.mask = value; - if (BX_VGA_THIS s.pel.mask != 0xff) - BX_DEBUG(("io write 3c6: PEL mask=0x%02x != 0xFF", value)); - // BX_VGA_THIS s.pel.mask should be and'd with final value before - // indexing into color register BX_VGA_THIS s.pel.data[] - break; - - case 0x03c7: // PEL address, read mode - BX_VGA_THIS s.pel.read_data_register = value; - BX_VGA_THIS s.pel.read_data_cycle = 0; - BX_VGA_THIS s.pel.dac_state = 0x03; - break; - - case 0x03c8: /* PEL address write mode */ - BX_VGA_THIS s.pel.write_data_register = value; - BX_VGA_THIS s.pel.write_data_cycle = 0; - BX_VGA_THIS s.pel.dac_state = 0x00; - break; - - case 0x03c9: /* PEL Data Register, colors 00..FF */ - switch (BX_VGA_THIS s.pel.write_data_cycle) { - case 0: - BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red = value; - break; - case 1: - BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green = value; - break; - case 2: - BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue = value; - - needs_update |= bx_gui->palette_change(BX_VGA_THIS s.pel.write_data_register, - BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red<<2, - BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green<<2, - BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue<<2); - break; - } - - BX_VGA_THIS s.pel.write_data_cycle++; - if (BX_VGA_THIS s.pel.write_data_cycle >= 3) { - //BX_INFO(("BX_VGA_THIS s.pel.data[%u] {r=%u, g=%u, b=%u}", - // (unsigned) BX_VGA_THIS s.pel.write_data_register, - // (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red, - // (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green, - // (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue); - BX_VGA_THIS s.pel.write_data_cycle = 0; - BX_VGA_THIS s.pel.write_data_register++; - } - break; - - case 0x03ca: /* Graphics 2 Position (EGA) */ - // ignore, EGA only??? - break; - - case 0x03cc: /* Graphics 1 Position (EGA) */ - // ignore, EGA only??? - break; - - case 0x03ce: /* Graphics Controller Index Register */ - if (value > 0x08) /* ??? */ - BX_DEBUG(("io write: 3ce: value > 8")); - BX_VGA_THIS s.graphics_ctrl.index = value; - break; - - case 0x03cd: /* ??? */ - BX_DEBUG(("io write to 03cd = %02x", (unsigned) value)); - break; - - case 0x03cf: /* Graphics Controller Registers 00..08 */ - switch (BX_VGA_THIS s.graphics_ctrl.index) { - case 0: /* Set/Reset */ - BX_VGA_THIS s.graphics_ctrl.set_reset = value & 0x0f; - break; - case 1: /* Enable Set/Reset */ - BX_VGA_THIS s.graphics_ctrl.enable_set_reset = value & 0x0f; - break; - case 2: /* Color Compare */ - BX_VGA_THIS s.graphics_ctrl.color_compare = value & 0x0f; - break; - case 3: /* Data Rotate */ - BX_VGA_THIS s.graphics_ctrl.data_rotate = value & 0x07; - /* ??? is this bits 3..4 or 4..5 */ - BX_VGA_THIS s.graphics_ctrl.raster_op = (value >> 3) & 0x03; /* ??? */ - break; - case 4: /* Read Map Select */ - BX_VGA_THIS s.graphics_ctrl.read_map_select = value & 0x03; -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("io write to 03cf = %02x (RMS)", (unsigned) value)); -#endif - break; - case 5: /* Mode */ - BX_VGA_THIS s.graphics_ctrl.write_mode = value & 0x03; - BX_VGA_THIS s.graphics_ctrl.read_mode = (value >> 3) & 0x01; - BX_VGA_THIS s.graphics_ctrl.odd_even = (value >> 4) & 0x01; - BX_VGA_THIS s.graphics_ctrl.shift_reg = (value >> 5) & 0x03; - - if (BX_VGA_THIS s.graphics_ctrl.odd_even) - BX_DEBUG(("io write: 3cf: reg 05: value = %02xh", - (unsigned) value)); - if (BX_VGA_THIS s.graphics_ctrl.shift_reg) - BX_DEBUG(("io write: 3cf: reg 05: value = %02xh", - (unsigned) value)); - break; - case 6: /* Miscellaneous */ - prev_graphics_alpha = BX_VGA_THIS s.graphics_ctrl.graphics_alpha; - prev_chain_odd_even = BX_VGA_THIS s.graphics_ctrl.chain_odd_even; - prev_memory_mapping = BX_VGA_THIS s.graphics_ctrl.memory_mapping; - - BX_VGA_THIS s.graphics_ctrl.graphics_alpha = value & 0x01; - BX_VGA_THIS s.graphics_ctrl.chain_odd_even = (value >> 1) & 0x01; - BX_VGA_THIS s.graphics_ctrl.memory_mapping = (value >> 2) & 0x03; -#if !defined(VGA_TRACE_FEATURE) - BX_DEBUG(("memory_mapping set to %u", - (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping)); - BX_DEBUG(("graphics mode set to %u", - (unsigned) BX_VGA_THIS s.graphics_ctrl.graphics_alpha)); - BX_DEBUG(("odd_even mode set to %u", - (unsigned) BX_VGA_THIS s.graphics_ctrl.odd_even)); - BX_DEBUG(("io write: 3cf: reg 06: value = %02xh", - (unsigned) value)); -#endif - if (prev_memory_mapping != BX_VGA_THIS s.graphics_ctrl.memory_mapping) - needs_update = 1; - if (prev_graphics_alpha != BX_VGA_THIS s.graphics_ctrl.graphics_alpha) { - needs_update = 1; - old_iHeight = 0; - } - break; - case 7: /* Color Don't Care */ - BX_VGA_THIS s.graphics_ctrl.color_dont_care = value & 0x0f; - break; - case 8: /* Bit Mask */ - BX_VGA_THIS s.graphics_ctrl.bitmask = value; - break; - default: - /* ??? */ - BX_DEBUG(("io write: 3cf: index %u unhandled", - (unsigned) BX_VGA_THIS s.graphics_ctrl.index)); - } - break; - - case 0x03b4: /* CRTC Index Register (monochrome emulation modes) */ - case 0x03d4: /* CRTC Index Register (color emulation modes) */ - BX_VGA_THIS s.CRTC.address = value & 0x7f; - if (BX_VGA_THIS s.CRTC.address > 0x18) - BX_DEBUG(("write: invalid CRTC register 0x%02x selected", - (unsigned) BX_VGA_THIS s.CRTC.address)); - break; - - case 0x03b5: /* CRTC Registers (monochrome emulation modes) */ - case 0x03d5: /* CRTC Registers (color emulation modes) */ - if (BX_VGA_THIS s.CRTC.address > 0x18) { - BX_DEBUG(("write: invalid CRTC register 0x%02x ignored", - (unsigned) BX_VGA_THIS s.CRTC.address)); - return; - } - if (value != BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address]) { - BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address] = value; - switch (BX_VGA_THIS s.CRTC.address) { - case 0x07: - BX_VGA_THIS s.vertical_display_end &= 0xff; - if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x02) BX_VGA_THIS s.vertical_display_end |= 0x100; - if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x40) BX_VGA_THIS s.vertical_display_end |= 0x200; - BX_VGA_THIS s.line_compare &= 0x2ff; - if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x10) BX_VGA_THIS s.line_compare |= 0x100; - needs_update = 1; - break; - case 0x08: - // Vertical pel panning change - needs_update = 1; - break; - case 0x09: - BX_VGA_THIS s.y_doublescan = ((value & 0x9f) > 0); - BX_VGA_THIS s.line_compare &= 0x1ff; - if (BX_VGA_THIS s.CRTC.reg[0x09] & 0x40) BX_VGA_THIS s.line_compare |= 0x200; - needs_update = 1; - break; - case 0x0A: - case 0x0B: - case 0x0E: - case 0x0F: - // Cursor size / location change - BX_VGA_THIS s.vga_mem_updated = 1; - break; - case 0x0C: - case 0x0D: - // Start address change - if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) { - needs_update = 1; - } else { - BX_VGA_THIS s.vga_mem_updated = 1; - } - break; - case 0x12: - BX_VGA_THIS s.vertical_display_end &= 0x300; - BX_VGA_THIS s.vertical_display_end |= BX_VGA_THIS s.CRTC.reg[0x12]; - break; - case 0x13: - case 0x14: - case 0x17: - // Line offset change - BX_VGA_THIS s.line_offset = BX_VGA_THIS s.CRTC.reg[0x13] << 1; - if (BX_VGA_THIS s.CRTC.reg[0x14] & 0x40) BX_VGA_THIS s.line_offset <<= 2; - else if ((BX_VGA_THIS s.CRTC.reg[0x17] & 0x40) == 0) BX_VGA_THIS s.line_offset <<= 1; - needs_update = 1; - break; - case 0x18: - BX_VGA_THIS s.line_compare &= 0x300; - BX_VGA_THIS s.line_compare |= BX_VGA_THIS s.CRTC.reg[0x18]; - needs_update = 1; - break; - } - - } - break; - - case 0x03da: /* Feature Control (color emulation modes) */ - BX_DEBUG(("io write: 3da: ignoring: feature ctrl & vert sync")); - break; - - case 0x03c1: /* */ - default: - BX_ERROR(("unsupported io write to port 0x%04x, val=0x%02x", - (unsigned) address, (unsigned) value)); - } - if (needs_update) { - BX_VGA_THIS s.vga_mem_updated = 1; - // Mark all video as updated so the changes will go through - if ((BX_VGA_THIS s.graphics_ctrl.graphics_alpha) -#if BX_SUPPORT_VBE - || (BX_VGA_THIS s.vbe_enabled) -#endif - ) { - for (unsigned xti = 0; xti < BX_NUM_X_TILES; xti++) { - for (unsigned yti = 0; yti < BX_NUM_Y_TILES; yti++) { - SET_TILE_UPDATED (xti, yti, 1); - } - } - } else { - memset(BX_VGA_THIS s.text_snapshot, 0, - sizeof(BX_VGA_THIS s.text_snapshot)); - } - } -} - -void -bx_vga_c::set_update_interval (unsigned interval) -{ - BX_INFO (("Changing timer interval to %d\n", interval)); - BX_VGA_THIS timer_handler (theVga); - bx_pc_system.activate_timer (BX_VGA_THIS timer_id, interval, 1); -} - - void -bx_vga_c::trigger_timer(void *this_ptr) -{ - timer_handler(this_ptr); -} - - void -bx_vga_c::timer_handler(void *this_ptr) -{ -#if !BX_USE_VGA_SMF - - bx_vga_c *class_ptr = (bx_vga_c *) this_ptr; - - class_ptr->timer(); -} - - void -bx_vga_c::timer(void) -{ -#else - UNUSED(this_ptr); -#endif - - update(); - bx_gui->flush(); - -} - - - void -bx_vga_c::update(void) -{ - unsigned iHeight, iWidth; - - /* no screen update necessary */ - if (BX_VGA_THIS s.vga_mem_updated==0) - return; - - /* skip screen update when the sequencer is in reset mode or video is disabled */ - if (!BX_VGA_THIS s.sequencer.reset1 || !BX_VGA_THIS s.sequencer.reset2 - || !BX_VGA_THIS s.attribute_ctrl.video_enabled) - return; - - /* skip screen update if the vertical retrace is in progress - (using 72 Hz vertical frequency) */ - if ((bx_pc_system.time_usec() % 13888) < 70) - return; - -#if BX_SUPPORT_VBE - if ((BX_VGA_THIS s.vbe_enabled) && (BX_VGA_THIS s.vbe_bpp != VBE_DISPI_BPP_4)) - { - // specific VBE code display update code - // this is partly copied/modified from the 320x200x8 update more below - unsigned xc, yc, xti, yti; - unsigned r; - unsigned long pixely, bmp_ofs_y, tile_ofs_y; - - if (BX_VGA_THIS s.vbe_bpp == VBE_DISPI_BPP_32) - { - Bit32u *vidmem = (Bit32u *)(&BX_VGA_THIS s.vbe_memory[BX_VGA_THIS s.vbe_virtual_start]); - Bit32u *tile = (Bit32u *)(BX_VGA_THIS s.tile); - Bit16u width = BX_VGA_THIS s.vbe_virtual_xres; - - Bit32u *vidptr, *tileptr; - - iWidth=BX_VGA_THIS s.vbe_xres; - iHeight=BX_VGA_THIS s.vbe_yres; - - for (yc=0, yti = 0; ycgraphics_tile_update(BX_VGA_THIS s.tile, xc, yc); - } - } - } - } - else if (BX_VGA_THIS s.vbe_bpp == VBE_DISPI_BPP_24) - { - Bit8u *vidmem = &BX_VGA_THIS s.vbe_memory[BX_VGA_THIS s.vbe_virtual_start]; - Bit8u *tile = BX_VGA_THIS s.tile; - Bit16u width = BX_VGA_THIS s.vbe_virtual_xres*3; - - Bit8u *vidptr, *tileptr; - - iWidth=BX_VGA_THIS s.vbe_xres; - iHeight=BX_VGA_THIS s.vbe_yres; - - for (yc=0, yti = 0; ycgraphics_tile_update(BX_VGA_THIS s.tile, xc, yc); - } - } - } - } - else if ((BX_VGA_THIS s.vbe_bpp == VBE_DISPI_BPP_15) || - (BX_VGA_THIS s.vbe_bpp == VBE_DISPI_BPP_16)) - { - Bit16u *vidmem = (Bit16u *)(&BX_VGA_THIS s.vbe_memory[BX_VGA_THIS s.vbe_virtual_start]); - Bit16u *tile = (Bit16u *)(BX_VGA_THIS s.tile); - Bit16u width = BX_VGA_THIS s.vbe_virtual_xres; - - Bit16u *vidptr, *tileptr; - - iWidth=BX_VGA_THIS s.vbe_xres; - iHeight=BX_VGA_THIS s.vbe_yres; - - for (yc=0, yti = 0; ycgraphics_tile_update(BX_VGA_THIS s.tile, xc, yc); - } - } - } - } - else /* Update 8bpp mode */ - { - Bit8u *vidmem = &BX_VGA_THIS s.vbe_memory[BX_VGA_THIS s.vbe_virtual_start]; - Bit8u *tile = BX_VGA_THIS s.tile; - Bit16u width = BX_VGA_THIS s.vbe_virtual_xres; - - Bit8u *vidptr, *tileptr; - - iWidth=BX_VGA_THIS s.vbe_xres; - iHeight=BX_VGA_THIS s.vbe_yres; - - for (yc=0, yti = 0; ycgraphics_tile_update(BX_VGA_THIS s.tile, xc, yc); - } - } - } - } - - old_iWidth = iWidth; - old_iHeight = iHeight; - BX_VGA_THIS s.vga_mem_updated = 0; - // after a vbe display update, don't try to do any 'normal vga' updates anymore - return; - } -#endif - // fields that effect the way video memory is serialized into screen output: - // GRAPHICS CONTROLLER: - // BX_VGA_THIS s.graphics_ctrl.shift_reg: - // 0: output data in standard VGA format or CGA-compatible 640x200 2 color - // graphics mode (mode 6) - // 1: output data in CGA-compatible 320x200 4 color graphics mode - // (modes 4 & 5) - // 2: output data 8 bits at a time from the 4 bit planes - // (mode 13 and variants like modeX) - - // if (BX_VGA_THIS s.vga_mem_updated==0 || BX_VGA_THIS s.attribute_ctrl.video_enabled == 0) - - if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) { - Bit8u color; - unsigned bit_no, r, c, x, y; - unsigned long byte_offset, start_addr; - unsigned xc, yc, xti, yti; - - start_addr = (BX_VGA_THIS s.CRTC.reg[0x0c] << 8) | BX_VGA_THIS s.CRTC.reg[0x0d]; - -//BX_DEBUG(("update: shiftreg=%u, chain4=%u, mapping=%u", -// (unsigned) BX_VGA_THIS s.graphics_ctrl.shift_reg, -// (unsigned) BX_VGA_THIS s.sequencer.chain_four, -// (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping); - - determine_screen_dimensions(&iHeight, &iWidth); - if( (iWidth != old_iWidth) || (iHeight != old_iHeight) || (old_BPP > 8) ) { - bx_gui->dimension_update(iWidth, iHeight); - old_iWidth = iWidth; - old_iHeight = iHeight; - old_BPP = 8; - } - - switch ( BX_VGA_THIS s.graphics_ctrl.shift_reg ) { - - case 0: - Bit8u attribute, palette_reg_val, DAC_regno; - unsigned long line_compare; - - if (BX_VGA_THIS s.graphics_ctrl.memory_mapping == 3) { // CGA 640x200x2 - - for (yc=0, yti=0; yc>= 1; - for (c=0; c> bit_no) & 1); - DAC_regno = BX_VGA_THIS s.attribute_ctrl.palette_reg[palette_reg_val]; - BX_VGA_THIS s.tile[r*X_TILESIZE + c] = DAC_regno; - } - } - SET_TILE_UPDATED (xti, yti, 0); - bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc); - } - } - } - } else { // output data in serial fashion with each display plane - // output on its associated serial output. Standard EGA/VGA format - - line_compare = BX_VGA_THIS s.line_compare; - if (BX_VGA_THIS s.y_doublescan) line_compare >>= 1; - - for (yc=0, yti=0; yc>= 1; - for (c=0; c>= 1; - bit_no = 7 - (x % 8); - if (y > line_compare) { - byte_offset = x / 8 + - ((y - line_compare - 1) * BX_VGA_THIS s.line_offset); - } else { - byte_offset = start_addr + x / 8 + - (y * BX_VGA_THIS s.line_offset); - } - attribute = - (((BX_VGA_THIS s.vga_memory[0*65536 + byte_offset] >> bit_no) & 0x01) << 0) | - (((BX_VGA_THIS s.vga_memory[1*65536 + byte_offset] >> bit_no) & 0x01) << 1) | - (((BX_VGA_THIS s.vga_memory[2*65536 + byte_offset] >> bit_no) & 0x01) << 2) | - (((BX_VGA_THIS s.vga_memory[3*65536 + byte_offset] >> bit_no) & 0x01) << 3); - - attribute &= BX_VGA_THIS s.attribute_ctrl.color_plane_enable; - // undocumented feature ???: colors 0..7 high intensity, colors 8..15 blinking - // using low/high intensity. Blinking is not implemented yet. - if (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity) attribute ^= 0x08; - palette_reg_val = BX_VGA_THIS s.attribute_ctrl.palette_reg[attribute]; - if (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size) { - // use 4 lower bits from palette register - // use 4 higher bits from color select register - // 16 banks of 16-color registers - DAC_regno = (palette_reg_val & 0x0f) | - (BX_VGA_THIS s.attribute_ctrl.color_select << 4); - } - else { - // use 6 lower bits from palette register - // use 2 higher bits from color select register - // 4 banks of 64-color registers - DAC_regno = (palette_reg_val & 0x3f) | - ((BX_VGA_THIS s.attribute_ctrl.color_select & 0x0c) << 4); - } - // DAC_regno &= video DAC mask register ??? - - BX_VGA_THIS s.tile[r*X_TILESIZE + c] = DAC_regno; - } - } - SET_TILE_UPDATED (xti, yti, 0); - bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc); - } - } - } - } - break; // case 0 - - case 1: // output the data in a CGA-compatible 320x200 4 color graphics - // mode. (modes 4 & 5) - - /* CGA 320x200x4 start */ - - for (yc=0, yti=0; yc>= 1; - for (c=0; c>= 1; - /* 0 or 0x2000 */ - byte_offset = start_addr + ((y & 1) << 13); - /* to the start of the line */ - byte_offset += (320 / 4) * (y / 2); - /* to the byte start */ - byte_offset += (x / 4); - - attribute = 6 - 2*(x % 4); - palette_reg_val = (BX_VGA_THIS s.vga_memory[byte_offset]) >> attribute; - palette_reg_val &= 3; - DAC_regno = BX_VGA_THIS s.attribute_ctrl.palette_reg[palette_reg_val]; - BX_VGA_THIS s.tile[r*X_TILESIZE + c] = DAC_regno; - } - } - SET_TILE_UPDATED (xti, yti, 0); - bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc); - } - } - } - /* CGA 320x200x4 end */ - - break; // case 1 - - case 2: // output the data eight bits at a time from the 4 bit plane - // (format for VGA mode 13 hex) - - if ( BX_VGA_THIS s.sequencer.chain_four ) { - unsigned long pixely, pixelx, plane; - // bx_vga_dump_status(); - - if (BX_VGA_THIS s.misc_output.select_high_bank != 1) - BX_PANIC(("update: select_high_bank != 1")); - - for (yc=0, yti=0; yc>= 1; - for (c=0; c> 1; - plane = (pixelx % 4); - byte_offset = start_addr + (plane * 65536) + - (pixely * BX_VGA_THIS s.line_offset) + (pixelx & ~0x03); - color = BX_VGA_THIS s.vga_memory[byte_offset]; - BX_VGA_THIS s.tile[r*X_TILESIZE + c] = color; - } - } - SET_TILE_UPDATED (xti, yti, 0); - bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc); - } - } - } - } - - else { // chain_four == 0, modeX - unsigned long pixely, pixelx, plane; - - for (yc=0, yti=0; yc>= 1; - for (c=0; c> 1; - plane = (pixelx % 4); - byte_offset = (plane * 65536) + - (pixely * BX_VGA_THIS s.line_offset) - + (pixelx >> 2); - color = BX_VGA_THIS s.vga_memory[start_addr + byte_offset]; - BX_VGA_THIS s.tile[r*X_TILESIZE + c] = color; - } - } - SET_TILE_UPDATED (xti, yti, 0); - bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc); - } - } - } - } - break; // case 2 - - default: - BX_PANIC(("update: shift_reg == %u", (unsigned) - BX_VGA_THIS s.graphics_ctrl.shift_reg )); - } - - BX_VGA_THIS s.vga_mem_updated = 0; - return; - } - - else { // text mode - unsigned long start_address; - unsigned long cursor_address, cursor_x, cursor_y; - bx_vga_tminfo_t tm_info; - - - tm_info.cs_start = BX_VGA_THIS s.CRTC.reg[0x0a] & 0x3f; - tm_info.cs_end = BX_VGA_THIS s.CRTC.reg[0x0b] & 0x1f; - tm_info.line_offset = BX_VGA_THIS s.CRTC.reg[0x13] << 2; - tm_info.line_compare = BX_VGA_THIS s.line_compare; - tm_info.h_panning = BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning & 0x0f; - tm_info.v_panning = BX_VGA_THIS s.CRTC.reg[0x08] & 0x1f; - tm_info.line_graphics = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics; - if ((BX_VGA_THIS s.sequencer.reg1 & 0x01) == 0) { - if (tm_info.h_panning == 8) - tm_info.h_panning = 0; - else - tm_info.h_panning++; - } - - switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) { - case 0: // 128K @ A0000 - case 1: // 64K @ A0000 - iWidth = 8*80; // TODO: should use font size - iHeight = 16*25; - if( (iWidth != old_iWidth) || (iHeight != old_iHeight) || (old_BPP > 8) ) - { - bx_gui->dimension_update(iWidth, iHeight, 16, 8); - old_iWidth = iWidth; - old_iHeight = iHeight; - old_BPP = 8; - } - /* pass old text snapshot & new VGA memory contents */ - start_address = 0x0; - cursor_address = 2*((BX_VGA_THIS s.CRTC.reg[0x0e] << 8) | - BX_VGA_THIS s.CRTC.reg[0x0f]); - if (cursor_address < start_address) { - cursor_x = 0xffff; - cursor_y = 0xffff; - } - else { - cursor_x = ((cursor_address - start_address)/2) % 80; - cursor_y = ((cursor_address - start_address)/2) / 80; - } - bx_gui->text_update(BX_VGA_THIS s.text_snapshot, - &BX_VGA_THIS s.vga_memory[start_address], - cursor_x, cursor_y, tm_info, 25); - // screen updated, copy new VGA memory contents into text snapshot - memcpy(BX_VGA_THIS s.text_snapshot, - &BX_VGA_THIS s.vga_memory[start_address], - 2*80*25); - BX_VGA_THIS s.vga_mem_updated = 0; - break; - - case 2: // B0000 .. B7FFF - case 3: // B8000 .. BFFFF - unsigned VDE, MSL, rows, cWidth; - - // Verticle Display End: find out how many lines are displayed - VDE = BX_VGA_THIS s.vertical_display_end; - // Maximum Scan Line: height of character cell - MSL = BX_VGA_THIS s.CRTC.reg[0x09] & 0x1f; - if (MSL == 0) { - //BX_ERROR(("character height = 1, skipping text update")); - return; - } - if ((MSL == 1) && (BX_VGA_THIS s.CRTC.reg[0x06] == 100)) { - // emulated CGA graphics mode 160x100x16 colors - MSL = 3; - rows = 100; - cWidth = 8; - iWidth = cWidth * BX_VGA_THIS s.CRTC.reg[1]; - iHeight = 400; - } else { - rows = (VDE+1)/(MSL+1); - if (rows > BX_MAX_TEXT_LINES) - BX_PANIC(("text rows>%d: %d",BX_MAX_TEXT_LINES,rows)); - cWidth = ((BX_VGA_THIS s.sequencer.reg1 & 0x01) == 1) ? 8 : 9; - iWidth = cWidth * (BX_VGA_THIS s.CRTC.reg[1] + 1); - iHeight = VDE+1; - } - if( (iWidth != old_iWidth) || (iHeight != old_iHeight) || (MSL != old_MSL) || (old_BPP > 8) ) - { - bx_gui->dimension_update(iWidth, iHeight, MSL+1, cWidth); - old_iWidth = iWidth; - old_iHeight = iHeight; - old_MSL = MSL; - old_BPP = 8; - } - // pass old text snapshot & new VGA memory contents - start_address = 2*((BX_VGA_THIS s.CRTC.reg[12] << 8) + BX_VGA_THIS s.CRTC.reg[13]); - cursor_address = 2*((BX_VGA_THIS s.CRTC.reg[0x0e] << 8) | - BX_VGA_THIS s.CRTC.reg[0x0f]); - if (cursor_address < start_address) { - cursor_x = 0xffff; - cursor_y = 0xffff; - } - else { - cursor_x = ((cursor_address - start_address)/2) % (iWidth/cWidth); - cursor_y = ((cursor_address - start_address)/2) / (iWidth/cWidth); - } - bx_gui->text_update(BX_VGA_THIS s.text_snapshot, - &BX_VGA_THIS s.vga_memory[start_address], - cursor_x, cursor_y, tm_info, rows); - // screen updated, copy new VGA memory contents into text snapshot - memcpy(BX_VGA_THIS s.text_snapshot, - &BX_VGA_THIS s.vga_memory[start_address], - 2*80*rows); - BX_VGA_THIS s.vga_mem_updated = 0; - break; - default: - BX_DEBUG(("update(): color text mode: mem map is %u", - (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping)); - } - } -} - - - Bit8u -bx_vga_c::mem_read(Bit32u addr) -{ - Bit32u offset; - -#if BX_SUPPORT_VBE - // if in a vbe enabled mode, read from the vbe_memory - if ((BX_VGA_THIS s.vbe_enabled) && (BX_VGA_THIS s.vbe_bpp != VBE_DISPI_BPP_4)) - { - return vbe_mem_read(addr); - } -#endif - -#if defined(VGA_TRACE_FEATURE) -// BX_DEBUG(("8-bit memory read from %08x", addr)); -#endif - -#ifdef __OS2__ - -#if BX_PLUGINS -#error Fix the code for plugins -#endif - - if ( bx_options.videomode == BX_VIDEO_DIRECT ) - { - char value; - - value = devices->mem->video[addr-0xA0000]; - - return value; - } -#endif - - switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) { - case 1: // 0xA0000 .. 0xAFFFF - if (addr > 0xAFFFF) return 0xff; - offset = addr - 0xA0000; - break; - case 2: // 0xB0000 .. 0xB7FFF - if ((addr < 0xB0000) || (addr > 0xB7FFF)) return 0xff; - return BX_VGA_THIS s.vga_memory[addr - 0xB0000]; - break; - case 3: // 0xB8000 .. 0xBFFFF - if (addr < 0xB8000) return 0xff; - return BX_VGA_THIS s.vga_memory[addr - 0xB8000]; - break; - default: // 0xA0000 .. 0xBFFFF - return BX_VGA_THIS s.vga_memory[addr - 0xA0000]; - } - - // addr between 0xA0000 and 0xAFFFF - if ( BX_VGA_THIS s.sequencer.chain_four ) { - - // Mode 13h: 320 x 200 256 color mode: chained pixel representation - return BX_VGA_THIS s.vga_memory[(offset & ~0x03) + (offset % 4)*65536]; - } - - /* addr between 0xA0000 and 0xAFFFF */ - switch (BX_VGA_THIS s.graphics_ctrl.read_mode) { - case 0: /* read mode 0 */ - BX_VGA_THIS s.graphics_ctrl.latch[0] = BX_VGA_THIS s.vga_memory[ offset]; - BX_VGA_THIS s.graphics_ctrl.latch[1] = BX_VGA_THIS s.vga_memory[1*65536 + offset]; - BX_VGA_THIS s.graphics_ctrl.latch[2] = BX_VGA_THIS s.vga_memory[2*65536 + offset]; - BX_VGA_THIS s.graphics_ctrl.latch[3] = BX_VGA_THIS s.vga_memory[3*65536 + offset]; - return(BX_VGA_THIS s.graphics_ctrl.latch[BX_VGA_THIS s.graphics_ctrl.read_map_select]); - break; - - case 1: /* read mode 1 */ - { - Bit8u color_compare, color_dont_care; - Bit8u latch0, latch1, latch2, latch3, retval; - - color_compare = BX_VGA_THIS s.graphics_ctrl.color_compare & 0x0f; - color_dont_care = BX_VGA_THIS s.graphics_ctrl.color_dont_care & 0x0f; - latch0 = BX_VGA_THIS s.graphics_ctrl.latch[0] = BX_VGA_THIS s.vga_memory[ offset]; - latch1 = BX_VGA_THIS s.graphics_ctrl.latch[1] = BX_VGA_THIS s.vga_memory[1*65536 + offset]; - latch2 = BX_VGA_THIS s.graphics_ctrl.latch[2] = BX_VGA_THIS s.vga_memory[2*65536 + offset]; - latch3 = BX_VGA_THIS s.graphics_ctrl.latch[3] = BX_VGA_THIS s.vga_memory[3*65536 + offset]; - - latch0 ^= ccdat[color_compare][0]; - latch1 ^= ccdat[color_compare][1]; - latch2 ^= ccdat[color_compare][2]; - latch3 ^= ccdat[color_compare][3]; - - latch0 &= ccdat[color_dont_care][0]; - latch1 &= ccdat[color_dont_care][1]; - latch2 &= ccdat[color_dont_care][2]; - latch3 &= ccdat[color_dont_care][3]; - - retval = ~(latch0 | latch1 | latch2 | latch3); - - return retval; - } - break; - default: - return 0; - } -} - - void -bx_vga_c::mem_write(Bit32u addr, Bit8u value) -{ - Bit32u offset; - Bit8u new_val[4]; - unsigned start_addr; - -#if BX_SUPPORT_VBE - // if in a vbe enabled mode, write to the vbe_memory - if ((BX_VGA_THIS s.vbe_enabled) && (BX_VGA_THIS s.vbe_bpp != VBE_DISPI_BPP_4)) - { - vbe_mem_write(addr,value); - return; - } -#endif - -#if defined(VGA_TRACE_FEATURE) -// BX_DEBUG(("8-bit memory write to %08x = %02x", addr, value)); -#endif - -#ifdef __OS2__ - -#if BX_PLUGINS -#error Fix the code for plugins -#endif - - if ( bx_options.videomode == BX_VIDEO_DIRECT ) - { - devices->mem->video[addr-0xA0000] = value; - - return; - } -#endif - - switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) { - case 1: // 0xA0000 .. 0xAFFFF - if (addr > 0xAFFFF) return; - offset = addr - 0xA0000; - break; - case 2: // 0xB0000 .. 0xB7FFF - if ((addr < 0xB0000) || (addr > 0xB7FFF)) return; - offset = addr - 0xB0000; - break; - case 3: // 0xB8000 .. 0xBFFFF - if (addr < 0xB8000) return; - offset = addr - 0xB8000; - break; - default: // 0xA0000 .. 0xBFFFF - offset = addr - 0xA0000; - } - - start_addr = (BX_VGA_THIS s.CRTC.reg[0x0c] << 8) | BX_VGA_THIS s.CRTC.reg[0x0d]; - - if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) { - if (BX_VGA_THIS s.graphics_ctrl.memory_mapping == 3) { // 0xB8000 .. 0xBFFFF - unsigned x_tileno, x_tileno2, y_tileno; - - /* CGA 320x200x4 / 640x200x2 start */ - BX_VGA_THIS s.vga_memory[offset] = value; - offset -= start_addr; - if (offset>=0x2000) { - y_tileno = offset - 0x2000; - y_tileno /= (320/4); - y_tileno <<= 1; //2 * y_tileno; - y_tileno++; - x_tileno = (offset - 0x2000) % (320/4); - x_tileno <<= 2; //*= 4; - } else { - y_tileno = offset / (320/4); - y_tileno <<= 1; //2 * y_tileno; - x_tileno = offset % (320/4); - x_tileno <<= 2; //*=4; - } - x_tileno2=x_tileno; - if (BX_VGA_THIS s.graphics_ctrl.shift_reg==0) { - x_tileno*=2; - x_tileno2+=7; - } else { - x_tileno2+=3; - } - if (BX_VGA_THIS s.x_dotclockdiv2) { - x_tileno/=(X_TILESIZE/2); - x_tileno2/=(X_TILESIZE/2); - } else { - x_tileno/=X_TILESIZE; - x_tileno2/=X_TILESIZE; - } - if (BX_VGA_THIS s.y_doublescan) { - y_tileno/=(Y_TILESIZE/2); - } else { - y_tileno/=Y_TILESIZE; - } - BX_VGA_THIS s.vga_mem_updated = 1; - SET_TILE_UPDATED (x_tileno, y_tileno, 1); - if (x_tileno2!=x_tileno) { - SET_TILE_UPDATED (x_tileno2, y_tileno, 1); - } - return; - /* CGA 320x200x4 / 640x200x2 end */ - } - else if (BX_VGA_THIS s.graphics_ctrl.memory_mapping != 1) { - - BX_PANIC(("mem_write: graphics: mapping = %u", - (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping)); - return; - } - - if ( BX_VGA_THIS s.sequencer.chain_four ) { - unsigned x_tileno, y_tileno; - - // 320 x 200 256 color mode: chained pixel representation - BX_VGA_THIS s.vga_memory[(offset & ~0x03) + (offset % 4)*65536] = value; - offset -= start_addr; - x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE/2); - if (BX_VGA_THIS s.y_doublescan) { - y_tileno = (offset / BX_VGA_THIS s.line_offset) / (Y_TILESIZE/2); - } else { - y_tileno = (offset / BX_VGA_THIS s.line_offset) / Y_TILESIZE; - } - BX_VGA_THIS s.vga_mem_updated = 1; - SET_TILE_UPDATED (x_tileno, y_tileno, 1); - return; - } - - } - - /* addr between 0xA0000 and 0xAFFFF */ - switch (BX_VGA_THIS s.graphics_ctrl.write_mode) { - unsigned i; - - case 0: /* write mode 0 */ - { - const Bit8u bitmask = BX_VGA_THIS s.graphics_ctrl.bitmask; - const Bit8u set_reset = BX_VGA_THIS s.graphics_ctrl.set_reset; - const Bit8u enable_set_reset = BX_VGA_THIS s.graphics_ctrl.enable_set_reset; - /* perform rotate on CPU data in case its needed */ - if (BX_VGA_THIS s.graphics_ctrl.data_rotate) { - value = (value >> BX_VGA_THIS s.graphics_ctrl.data_rotate) | - (value << (8 - BX_VGA_THIS s.graphics_ctrl.data_rotate)); - } - new_val[0] = BX_VGA_THIS s.graphics_ctrl.latch[0] & ~bitmask; - new_val[1] = BX_VGA_THIS s.graphics_ctrl.latch[1] & ~bitmask; - new_val[2] = BX_VGA_THIS s.graphics_ctrl.latch[2] & ~bitmask; - new_val[3] = BX_VGA_THIS s.graphics_ctrl.latch[3] & ~bitmask; - switch (BX_VGA_THIS s.graphics_ctrl.raster_op) { - case 0: // replace - new_val[0] |= ((enable_set_reset & 1) - ? ((set_reset & 1) ? bitmask : 0) - : (value & bitmask)); - new_val[1] |= ((enable_set_reset & 2) - ? ((set_reset & 2) ? bitmask : 0) - : (value & bitmask)); - new_val[2] |= ((enable_set_reset & 4) - ? ((set_reset & 4) ? bitmask : 0) - : (value & bitmask)); - new_val[3] |= ((enable_set_reset & 8) - ? ((set_reset & 8) ? bitmask : 0) - : (value & bitmask)); - break; - case 1: // AND - new_val[0] |= ((enable_set_reset & 1) - ? ((set_reset & 1) - ? (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask) - : 0) - : (value & BX_VGA_THIS s.graphics_ctrl.latch[0]) & bitmask); - new_val[1] |= ((enable_set_reset & 2) - ? ((set_reset & 2) - ? (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask) - : 0) - : (value & BX_VGA_THIS s.graphics_ctrl.latch[1]) & bitmask); - new_val[2] |= ((enable_set_reset & 4) - ? ((set_reset & 4) - ? (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask) - : 0) - : (value & BX_VGA_THIS s.graphics_ctrl.latch[2]) & bitmask); - new_val[3] |= ((enable_set_reset & 8) - ? ((set_reset & 8) - ? (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask) - : 0) - : (value & BX_VGA_THIS s.graphics_ctrl.latch[3]) & bitmask); - break; - case 2: // OR - new_val[0] - |= ((enable_set_reset & 1) - ? ((set_reset & 1) - ? bitmask - : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)) - : ((value | BX_VGA_THIS s.graphics_ctrl.latch[0]) & bitmask)); - new_val[1] - |= ((enable_set_reset & 2) - ? ((set_reset & 2) - ? bitmask - : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)) - : ((value | BX_VGA_THIS s.graphics_ctrl.latch[1]) & bitmask)); - new_val[2] - |= ((enable_set_reset & 4) - ? ((set_reset & 4) - ? bitmask - : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)) - : ((value | BX_VGA_THIS s.graphics_ctrl.latch[2]) & bitmask)); - new_val[3] - |= ((enable_set_reset & 8) - ? ((set_reset & 8) - ? bitmask - : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)) - : ((value | BX_VGA_THIS s.graphics_ctrl.latch[3]) & bitmask)); - break; - case 3: // XOR - new_val[0] - |= ((enable_set_reset & 1) - ? ((set_reset & 1) - ? (~BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask) - : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)) - : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[0]) & bitmask); - new_val[1] - |= ((enable_set_reset & 2) - ? ((set_reset & 2) - ? (~BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask) - : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)) - : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[1]) & bitmask); - new_val[2] - |= ((enable_set_reset & 4) - ? ((set_reset & 4) - ? (~BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask) - : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)) - : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[2]) & bitmask); - new_val[3] - |= ((enable_set_reset & 8) - ? ((set_reset & 8) - ? (~BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask) - : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)) - : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[3]) & bitmask); - break; - default: - BX_PANIC(("vga_mem_write: write mode 0: op = %u", - (unsigned) BX_VGA_THIS s.graphics_ctrl.raster_op)); - } - } - break; - - case 1: /* write mode 1 */ - for (i=0; i<4; i++ ) { - new_val[i] = BX_VGA_THIS s.graphics_ctrl.latch[i]; - } - break; - - case 2: /* write mode 2 */ - { - const Bit8u bitmask = BX_VGA_THIS s.graphics_ctrl.bitmask; - - new_val[0] = BX_VGA_THIS s.graphics_ctrl.latch[0] & ~bitmask; - new_val[1] = BX_VGA_THIS s.graphics_ctrl.latch[1] & ~bitmask; - new_val[2] = BX_VGA_THIS s.graphics_ctrl.latch[2] & ~bitmask; - new_val[3] = BX_VGA_THIS s.graphics_ctrl.latch[3] & ~bitmask; - switch (BX_VGA_THIS s.graphics_ctrl.raster_op) { - case 0: // write - new_val[0] |= (value & 1) ? bitmask : 0; - new_val[1] |= (value & 2) ? bitmask : 0; - new_val[2] |= (value & 4) ? bitmask : 0; - new_val[3] |= (value & 8) ? bitmask : 0; - break; - case 1: // AND - new_val[0] |= (value & 1) - ? (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask) - : 0; - new_val[1] |= (value & 2) - ? (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask) - : 0; - new_val[2] |= (value & 4) - ? (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask) - : 0; - new_val[3] |= (value & 8) - ? (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask) - : 0; - break; - case 2: // OR - new_val[0] |= (value & 1) - ? bitmask - : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask); - new_val[1] |= (value & 2) - ? bitmask - : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask); - new_val[2] |= (value & 4) - ? bitmask - : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask); - new_val[3] |= (value & 8) - ? bitmask - : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask); - break; - case 3: // XOR - new_val[0] |= (value & 1) - ? (~BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask) - : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask); - new_val[1] |= (value & 2) - ? (~BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask) - : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask); - new_val[2] |= (value & 4) - ? (~BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask) - : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask); - new_val[3] |= (value & 8) - ? (~BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask) - : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask); - break; - } - } - break; - - case 3: /* write mode 3 */ - { - const Bit8u bitmask = BX_VGA_THIS s.graphics_ctrl.bitmask & value; - const Bit8u set_reset = BX_VGA_THIS s.graphics_ctrl.set_reset; - - /* perform rotate on CPU data */ - if (BX_VGA_THIS s.graphics_ctrl.data_rotate) { - value = (value >> BX_VGA_THIS s.graphics_ctrl.data_rotate) | - (value << (8 - BX_VGA_THIS s.graphics_ctrl.data_rotate)); - } - new_val[0] = BX_VGA_THIS s.graphics_ctrl.latch[0] & ~bitmask; - new_val[1] = BX_VGA_THIS s.graphics_ctrl.latch[1] & ~bitmask; - new_val[2] = BX_VGA_THIS s.graphics_ctrl.latch[2] & ~bitmask; - new_val[3] = BX_VGA_THIS s.graphics_ctrl.latch[3] & ~bitmask; - - value &= bitmask; - - switch (BX_VGA_THIS s.graphics_ctrl.raster_op) { - case 0: // write - new_val[0] |= (set_reset & 1) ? value : 0; - new_val[1] |= (set_reset & 2) ? value : 0; - new_val[2] |= (set_reset & 4) ? value : 0; - new_val[3] |= (set_reset & 8) ? value : 0; - break; - case 1: // AND - new_val[0] |= ((set_reset & 1) ? value : 0) - & BX_VGA_THIS s.graphics_ctrl.latch[0]; - new_val[1] |= ((set_reset & 2) ? value : 0) - & BX_VGA_THIS s.graphics_ctrl.latch[1]; - new_val[2] |= ((set_reset & 4) ? value : 0) - & BX_VGA_THIS s.graphics_ctrl.latch[2]; - new_val[3] |= ((set_reset & 8) ? value : 0) - & BX_VGA_THIS s.graphics_ctrl.latch[3]; - break; - case 2: // OR - new_val[0] |= ((set_reset & 1) ? value : 0) - | BX_VGA_THIS s.graphics_ctrl.latch[0]; - new_val[1] |= ((set_reset & 2) ? value : 0) - | BX_VGA_THIS s.graphics_ctrl.latch[1]; - new_val[2] |= ((set_reset & 4) ? value : 0) - | BX_VGA_THIS s.graphics_ctrl.latch[2]; - new_val[3] |= ((set_reset & 8) ? value : 0) - | BX_VGA_THIS s.graphics_ctrl.latch[3]; - break; - case 3: // XOR - new_val[0] |= ((set_reset & 1) ? value : 0) - ^ BX_VGA_THIS s.graphics_ctrl.latch[0]; - new_val[1] |= ((set_reset & 2) ? value : 0) - ^ BX_VGA_THIS s.graphics_ctrl.latch[1]; - new_val[2] |= ((set_reset & 4) ? value : 0) - ^ BX_VGA_THIS s.graphics_ctrl.latch[2]; - new_val[3] |= ((set_reset & 8) ? value : 0) - ^ BX_VGA_THIS s.graphics_ctrl.latch[3]; - break; - } - } - break; - - default: - BX_PANIC(("vga_mem_write: write mode %u ?", - (unsigned) BX_VGA_THIS s.graphics_ctrl.write_mode)); - } - - if (BX_VGA_THIS s.sequencer.map_mask & 0x0f) { - BX_VGA_THIS s.vga_mem_updated = 1; - if (BX_VGA_THIS s.sequencer.map_mask_bit[0]) - BX_VGA_THIS s.vga_memory[0*65536 + offset] = new_val[0]; - if (BX_VGA_THIS s.sequencer.map_mask_bit[1]) - BX_VGA_THIS s.vga_memory[1*65536 + offset] = new_val[1]; - if (BX_VGA_THIS s.sequencer.map_mask_bit[2]) { - if ((!BX_VGA_THIS s.graphics_ctrl.graphics_alpha) && - ((offset & 0xe000) == BX_VGA_THIS s.charmap_address)) { - bx_gui->set_text_charbyte((offset & 0x1fff), new_val[2]); - } - BX_VGA_THIS s.vga_memory[2*65536 + offset] = new_val[2]; - } - if (BX_VGA_THIS s.sequencer.map_mask_bit[3]) - BX_VGA_THIS s.vga_memory[3*65536 + offset] = new_val[3]; - - unsigned x_tileno, y_tileno; - - if (BX_VGA_THIS s.graphics_ctrl.shift_reg == 2) { - offset -= start_addr; - x_tileno = (offset % BX_VGA_THIS s.line_offset) * 4 / (X_TILESIZE / 2); - if (BX_VGA_THIS s.y_doublescan) { - y_tileno = (offset / BX_VGA_THIS s.line_offset) / (Y_TILESIZE / 2); - } else { - y_tileno = (offset / BX_VGA_THIS s.line_offset) / Y_TILESIZE; - } - SET_TILE_UPDATED (x_tileno, y_tileno, 1); - } else { - if (BX_VGA_THIS s.line_compare < BX_VGA_THIS s.vertical_display_end) { - if (BX_VGA_THIS s.x_dotclockdiv2) { - x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 16); - } else { - x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 8); - } - if (BX_VGA_THIS s.y_doublescan) { - y_tileno = ((offset / BX_VGA_THIS s.line_offset) * 2 + BX_VGA_THIS s.line_compare + 1) / Y_TILESIZE; - } else { - y_tileno = ((offset / BX_VGA_THIS s.line_offset) + BX_VGA_THIS s.line_compare + 1) / Y_TILESIZE; - } - SET_TILE_UPDATED (x_tileno, y_tileno, 1); - } - if (offset >= start_addr) { - offset -= start_addr; - if (BX_VGA_THIS s.x_dotclockdiv2) { - x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 16); - } else { - x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 8); - } - if (BX_VGA_THIS s.y_doublescan) { - y_tileno = (offset / BX_VGA_THIS s.line_offset) / (Y_TILESIZE / 2); - } else { - y_tileno = (offset / BX_VGA_THIS s.line_offset) / Y_TILESIZE; - } - SET_TILE_UPDATED (x_tileno, y_tileno, 1); - } - } - } -} - - void -bx_vga_c::get_text_snapshot(Bit8u **text_snapshot, unsigned *txHeight, - unsigned *txWidth) -{ - unsigned VDE, MSL; - - if (!BX_VGA_THIS s.graphics_ctrl.graphics_alpha) { - *text_snapshot = &BX_VGA_THIS s.text_snapshot[0]; - VDE = BX_VGA_THIS s.vertical_display_end; - MSL = BX_VGA_THIS s.CRTC.reg[0x09] & 0x1f; - *txHeight = (VDE+1)/(MSL+1); - *txWidth = BX_VGA_THIS s.CRTC.reg[1] + 1; - } else { - *txHeight = 0; - *txWidth = 0; - } -} - - Bit8u -bx_vga_c::get_actl_palette_idx(Bit8u index) -{ - return BX_VGA_THIS s.attribute_ctrl.palette_reg[index]; -} - - void -bx_vga_c::dump_status(void) -{ - BX_INFO(("s.misc_output.color_emulation = %u", - (unsigned) BX_VGA_THIS s.misc_output.color_emulation)); - BX_INFO(("s.misc_output.enable_ram = %u", - (unsigned) BX_VGA_THIS s.misc_output.enable_ram)); - BX_INFO(("s.misc_output.clock_select = %u", - (unsigned) BX_VGA_THIS s.misc_output.clock_select)); - if (BX_VGA_THIS s.misc_output.clock_select == 0) - BX_INFO((" 25Mhz 640 horiz pixel clock")); - else - BX_INFO((" 28Mhz 720 horiz pixel clock")); - BX_INFO(("s.misc_output.select_high_bank = %u", - (unsigned) BX_VGA_THIS s.misc_output.select_high_bank)); - BX_INFO(("s.misc_output.horiz_sync_pol = %u", - (unsigned) BX_VGA_THIS s.misc_output.horiz_sync_pol)); - BX_INFO(("s.misc_output.vert_sync_pol = %u", - (unsigned) BX_VGA_THIS s.misc_output.vert_sync_pol)); - switch ( (BX_VGA_THIS s.misc_output.vert_sync_pol << 1) | - BX_VGA_THIS s.misc_output.horiz_sync_pol ) { - case 0: BX_INFO((" (reserved")); break; - case 1: BX_INFO((" 400 lines")); break; - case 2: BX_INFO((" 350 lines")); break; - case 3: BX_INFO((" 480 lines")); break; - default: BX_INFO((" ???")); - } - - BX_INFO(("s.graphics_ctrl.odd_even = %u", - (unsigned) BX_VGA_THIS s.graphics_ctrl.odd_even)); - BX_INFO(("s.graphics_ctrl.chain_odd_even = %u", - (unsigned) BX_VGA_THIS s.graphics_ctrl.chain_odd_even)); - BX_INFO(("s.graphics_ctrl.shift_reg = %u", - (unsigned) BX_VGA_THIS s.graphics_ctrl.shift_reg)); - BX_INFO(("s.graphics_ctrl.graphics_alpha = %u", - (unsigned) BX_VGA_THIS s.graphics_ctrl.graphics_alpha)); - BX_INFO(("s.graphics_ctrl.memory_mapping = %u", - (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping)); - switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) { - case 0: BX_INFO((" A0000-BFFFF")); break; - case 1: BX_INFO((" A0000-AFFFF")); break; - case 2: BX_INFO((" B0000-B7FFF")); break; - case 3: BX_INFO((" B8000-BFFFF")); break; - default: BX_INFO((" ???")); - } - - BX_INFO(("s.sequencer.extended_mem = %u", - (unsigned) BX_VGA_THIS s.sequencer.extended_mem)); - BX_INFO(("s.sequencer.odd_even = %u (inverted)", - (unsigned) BX_VGA_THIS s.sequencer.odd_even)); - BX_INFO(("s.sequencer.chain_four = %u", - (unsigned) BX_VGA_THIS s.sequencer.chain_four)); - - BX_INFO(("s.attribute_ctrl.video_enabled = %u", - (unsigned) BX_VGA_THIS s.attribute_ctrl.video_enabled)); - BX_INFO(("s.attribute_ctrl.mode_ctrl.graphics_alpha = %u", - (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha)); - BX_INFO(("s.attribute_ctrl.mode_ctrl.display_type = %u", - (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type)); - BX_INFO(("s.attribute_ctrl.mode_ctrl.internal_palette_size = %u", - (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size)); - BX_INFO(("s.attribute_ctrl.mode_ctrl.pixel_clock_select = %u", - (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select)); -} - - - void -bx_vga_c::redraw_area(unsigned x0, unsigned y0, unsigned width, - unsigned height) -{ - unsigned xi, yi, x1, y1, xmax, ymax; - - BX_VGA_THIS s.vga_mem_updated = 1; - -#if BX_SUPPORT_VBE - if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha || BX_VGA_THIS s.vbe_enabled) { -#else - if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) { -#endif - // graphics mode - x1 = x0 + width - 1; - y1 = y0 + height - 1; - - xmax = old_iWidth; - ymax = old_iHeight; -#if BX_SUPPORT_VBE - if (BX_VGA_THIS s.vbe_enabled) { - xmax = BX_VGA_THIS s.vbe_xres; - ymax = BX_VGA_THIS s.vbe_yres; - } -#endif - for (yi=0; yi (xi+X_TILESIZE-1)) continue; - - // is redraw rectangle outside y boundaries of this tile? - if (y1 < yi) continue; - if (y0 > (yi+Y_TILESIZE-1)) continue; - unsigned xti = xi/X_TILESIZE; - unsigned yti = yi/Y_TILESIZE; - SET_TILE_UPDATED (xti, yti, 1); - } - } - } - else { - // text mode - memset(BX_VGA_THIS s.text_snapshot, 0, - sizeof(BX_VGA_THIS s.text_snapshot)); - } -} - - -#if BX_SUPPORT_VBE - Bit8u BX_CPP_AttrRegparmN(1) -bx_vga_c::vbe_mem_read(Bit32u addr) -{ - Bit32u offset; - - if (addr >= VBE_DISPI_LFB_PHYSICAL_ADDRESS) - { - // LFB read - offset = addr - VBE_DISPI_LFB_PHYSICAL_ADDRESS; - } - else - { - // banked mode read - offset = BX_VGA_THIS s.vbe_bank*65536 + addr - 0xA0000; - } - - // check for out of memory read - if (offset > VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES) - return 0; - - return (BX_VGA_THIS s.vbe_memory[offset]); -} - - void BX_CPP_AttrRegparmN(2) -bx_vga_c::vbe_mem_write(Bit32u addr, Bit8u value) -{ - Bit32u offset; - unsigned x_tileno, y_tileno; - - if (BX_VGA_THIS s.vbe_lfb_enabled) - { - if (addr >= VBE_DISPI_LFB_PHYSICAL_ADDRESS) - { - // LFB write - offset = addr - VBE_DISPI_LFB_PHYSICAL_ADDRESS; - } - else - { - // banked mode write while in LFB mode -> ignore - return; - } - } - else - { - if (addr < VBE_DISPI_LFB_PHYSICAL_ADDRESS) - { - // banked mode write - offset = (BX_VGA_THIS s.vbe_bank*65536) + (addr - 0xA0000); - } - else - { - // LFB write while in banked mode -> ignore - return; - } - } - - // check for out of memory write - if (offset < VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES) - { - BX_VGA_THIS s.vbe_memory[offset]=value; - } - else - { - // make sure we don't flood the logfile - static int count=0; - if (count<100) - { - count ++; - BX_INFO(("VBE_mem_write out of video memory write at %x",offset)); - } - } - - offset-=BX_VGA_THIS s.vbe_virtual_start; - - // only update the UI when writing 'onscreen' - if (offset < BX_VGA_THIS s.vbe_visable_screen_size) - { - y_tileno = ((offset / BX_VGA_THIS s.vbe_bpp_multiplier) / BX_VGA_THIS s.vbe_virtual_xres) / Y_TILESIZE; - x_tileno = ((offset / BX_VGA_THIS s.vbe_bpp_multiplier) % BX_VGA_THIS s.vbe_virtual_xres) / X_TILESIZE; - - if ((y_tileno < BX_NUM_Y_TILES) && (x_tileno < BX_NUM_X_TILES)) - { - BX_VGA_THIS s.vga_mem_updated = 1; - SET_TILE_UPDATED (x_tileno, y_tileno, 1); - } - } -} - - Bit32u -bx_vga_c::vbe_read_handler(void *this_ptr, Bit32u address, unsigned io_len) -{ -#if !BX_USE_VGA_SMF - bx_vga_c *class_ptr = (bx_vga_c *) this_ptr; - - return( class_ptr->vbe_read(address, io_len) ); -} - - - Bit32u -bx_vga_c::vbe_read(Bit32u address, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif // !BX_USE_VGA_SMF - -// BX_INFO(("VBE_read %x (len %x)", address, io_len)); - - if ((address==VBE_DISPI_IOPORT_INDEX) || - (address==VBE_DISPI_IOPORT_INDEX_OLD)) - { - // index register - return (Bit32u) BX_VGA_THIS s.vbe_curindex; - } - else - { - // data register read - - switch (BX_VGA_THIS s.vbe_curindex) - { - case VBE_DISPI_INDEX_ID: // Display Interface ID check - { - return BX_VGA_THIS s.vbe_cur_dispi; - } break; - - case VBE_DISPI_INDEX_XRES: // x resolution - { - return BX_VGA_THIS s.vbe_xres; - } break; - - case VBE_DISPI_INDEX_YRES: // y resolution - { - return BX_VGA_THIS s.vbe_yres; - } break; - - case VBE_DISPI_INDEX_BPP: // bpp - { - return BX_VGA_THIS s.vbe_bpp; - } break; - - case VBE_DISPI_INDEX_ENABLE: // vbe enabled - { - return BX_VGA_THIS s.vbe_enabled; - } break; - - case VBE_DISPI_INDEX_BANK: // current bank - { - return BX_VGA_THIS s.vbe_bank; - } break; - - case VBE_DISPI_INDEX_X_OFFSET: - { - return BX_VGA_THIS s.vbe_offset_x; - } break; - - case VBE_DISPI_INDEX_Y_OFFSET: - { - return BX_VGA_THIS s.vbe_offset_y; - } break; - - case VBE_DISPI_INDEX_VIRT_WIDTH: - { - return BX_VGA_THIS s.vbe_virtual_xres; - - } break; - - case VBE_DISPI_INDEX_VIRT_HEIGHT: - { - return BX_VGA_THIS s.vbe_virtual_yres; - } break; - - - default: - { - BX_PANIC(("VBE unknown data read index 0x%x",BX_VGA_THIS s.vbe_curindex)); - } break; - } - } - BX_PANIC(("VBE_read shouldn't reach this")); - return 0; /* keep compiler happy */ -} - - void -bx_vga_c::vbe_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) -{ -#if !BX_USE_VGA_SMF - bx_vga_c *class_ptr = (bx_vga_c *) this_ptr; - - class_ptr->vbe_write(address, value, io_len); -} - - Bit32u -bx_vga_c::vbe_write(Bit32u address, Bit32u value, unsigned io_len) -{ -#else - UNUSED(this_ptr); -#endif - -// BX_INFO(("VBE_write %x = %x (len %x)", address, value, io_len)); - - switch(address) - { - // index register - case VBE_DISPI_IOPORT_INDEX: - // legacy index register - case VBE_DISPI_IOPORT_INDEX_OLD: - - BX_VGA_THIS s.vbe_curindex = (Bit16u) value; - break; - - // data register - // FIXME: maybe do some 'sanity' checks on received data? - case VBE_DISPI_IOPORT_DATA: - // legacy data register - case VBE_DISPI_IOPORT_DATA_OLD: - switch (BX_VGA_THIS s.vbe_curindex) - { - case VBE_DISPI_INDEX_ID: // Display Interface ID check - { - if ( (value == VBE_DISPI_ID0) || - (value == VBE_DISPI_ID1) || - (value == VBE_DISPI_ID2) ) - { - // allow backwards compatible with previous dispi bioses - BX_VGA_THIS s.vbe_cur_dispi=value; - } - else - { - BX_PANIC(("VBE unknown Display Interface %x",value)); - } - - // make sure we don't flood the logfile - static int count=0; - if (count < 100) - { - count++; - BX_INFO(("VBE known Display Interface %x",value)); - } - } break; - - case VBE_DISPI_INDEX_XRES: // set xres - { - // check that we don't set xres during vbe enabled - if (!BX_VGA_THIS s.vbe_enabled) - { - // check for within max xres range - if (value <= VBE_DISPI_MAX_XRES) - { - BX_VGA_THIS s.vbe_xres=(Bit16u) value; - BX_INFO(("VBE set xres (%d)",value)); - } - else - { - BX_INFO(("VBE set xres more then max xres (%d)",value)); - } - } - else - { - BX_INFO(("VBE set xres during vbe enabled!")); - } - } break; - - case VBE_DISPI_INDEX_YRES: // set yres - { - // check that we don't set yres during vbe enabled - if (!BX_VGA_THIS s.vbe_enabled) - { - // check for within max yres range - if (value <= VBE_DISPI_MAX_YRES) - { - BX_VGA_THIS s.vbe_yres=(Bit16u) value; - BX_INFO(("VBE set yres (%d)",value)); - } - else - { - BX_INFO(("VBE set yres more then max yres (%d)",value)); - } - } - else - { - BX_INFO(("VBE set yres during vbe enabled!")); - } - } break; - - case VBE_DISPI_INDEX_BPP: // set bpp - { - // check that we don't set bpp during vbe enabled - if (!BX_VGA_THIS s.vbe_enabled) - { - // for backward compatiblity - if (value == 0) value = VBE_DISPI_BPP_8; - // check for correct bpp range - if ((value == VBE_DISPI_BPP_4) || (value == VBE_DISPI_BPP_8) || (value == VBE_DISPI_BPP_15) || - (value == VBE_DISPI_BPP_16) || (value == VBE_DISPI_BPP_24) || (value == VBE_DISPI_BPP_32)) - { - BX_VGA_THIS s.vbe_bpp=(Bit16u) value; - BX_INFO(("VBE set bpp (%d)",value)); - } - else - { - BX_INFO(("VBE set bpp with unknown bpp (%d)",value)); - } - } - else - { - BX_INFO(("VBE set bpp during vbe enabled!")); - } - } break; - - case VBE_DISPI_INDEX_BANK: // set bank - { - value=value & 0xff ; // FIXME lobyte = vbe bank A? - - // check for max bank nr - if (value < (VBE_DISPI_TOTAL_VIDEO_MEMORY_KB /64)) - { - if (!BX_VGA_THIS s.vbe_lfb_enabled) - { - BX_DEBUG(("VBE set bank to %d", value)); - BX_VGA_THIS s.vbe_bank=value; - } - else - { - BX_ERROR(("VBE set bank in LFB mode ignored")); - } - } - else - { - BX_INFO(("VBE set invalid bank (%d)",value)); - } - } break; - - case VBE_DISPI_INDEX_ENABLE: // enable video - { - if (value & VBE_DISPI_ENABLED) - { - unsigned depth=0; - - // setup virtual resolution to be the same as current reso - BX_VGA_THIS s.vbe_virtual_yres=BX_VGA_THIS s.vbe_yres; - BX_VGA_THIS s.vbe_virtual_xres=BX_VGA_THIS s.vbe_xres; - - // reset offset - BX_VGA_THIS s.vbe_offset_x=0; - BX_VGA_THIS s.vbe_offset_y=0; - BX_VGA_THIS s.vbe_virtual_start=0; - - switch((BX_VGA_THIS s.vbe_bpp)) - { - // Default pixel sizes - case VBE_DISPI_BPP_8: - BX_VGA_THIS s.vbe_bpp_multiplier = 1; - BX_VGA_THIS s.vbe_line_byte_width = BX_VGA_THIS s.vbe_virtual_xres; - BX_VGA_THIS s.vbe_visable_screen_size = ((BX_VGA_THIS s.vbe_xres) * (BX_VGA_THIS s.vbe_yres)); - depth=8; - break; - - case VBE_DISPI_BPP_4: - BX_VGA_THIS s.vbe_bpp_multiplier = 1; - BX_VGA_THIS s.vbe_line_byte_width = BX_VGA_THIS s.vbe_virtual_xres; - BX_VGA_THIS s.vbe_visable_screen_size = ((BX_VGA_THIS s.vbe_xres) * (BX_VGA_THIS s.vbe_yres)); - depth=4; - break; - - case VBE_DISPI_BPP_15: - BX_VGA_THIS s.vbe_bpp_multiplier = 2; - BX_VGA_THIS s.vbe_line_byte_width = BX_VGA_THIS s.vbe_virtual_xres * 2; - BX_VGA_THIS s.vbe_visable_screen_size = ((BX_VGA_THIS s.vbe_xres) * (BX_VGA_THIS s.vbe_yres)) * 2; - depth=15; - break; - - case VBE_DISPI_BPP_16: - BX_VGA_THIS s.vbe_bpp_multiplier = 2; - BX_VGA_THIS s.vbe_line_byte_width = BX_VGA_THIS s.vbe_virtual_xres * 2; - BX_VGA_THIS s.vbe_visable_screen_size = ((BX_VGA_THIS s.vbe_xres) * (BX_VGA_THIS s.vbe_yres)) * 2; - depth=16; - break; - - case VBE_DISPI_BPP_24: - BX_VGA_THIS s.vbe_bpp_multiplier = 3; - BX_VGA_THIS s.vbe_line_byte_width = BX_VGA_THIS s.vbe_virtual_xres * 3; - BX_VGA_THIS s.vbe_visable_screen_size = ((BX_VGA_THIS s.vbe_xres) * (BX_VGA_THIS s.vbe_yres)) * 3; - depth=24; - break; - - case VBE_DISPI_BPP_32: - BX_VGA_THIS s.vbe_bpp_multiplier = 4; - BX_VGA_THIS s.vbe_line_byte_width = BX_VGA_THIS s.vbe_virtual_xres << 2; - BX_VGA_THIS s.vbe_visable_screen_size = ((BX_VGA_THIS s.vbe_xres) * (BX_VGA_THIS s.vbe_yres)) << 2; - depth=32; - break; - } - - BX_INFO(("VBE enabling x %d, y %d, bpp %d, %u bytes visible", BX_VGA_THIS s.vbe_xres, BX_VGA_THIS s.vbe_yres, BX_VGA_THIS s.vbe_bpp, BX_VGA_THIS s.vbe_visable_screen_size)); - - if (depth > 4) - { - BX_VGA_THIS s.vbe_lfb_enabled=(bx_bool)(value & VBE_DISPI_LFB_ENABLED); - if ((value & VBE_DISPI_NOCLEARMEM) == 0) - { - memset(BX_VGA_THIS s.vbe_memory, 0, BX_VGA_THIS s.vbe_visable_screen_size); - } - bx_gui->dimension_update(BX_VGA_THIS s.vbe_xres, BX_VGA_THIS s.vbe_yres, 0, 0, depth); - old_BPP = depth; - // some test applications expect these standard VGA settings - BX_VGA_THIS s.CRTC.reg[9] = 0x00; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha = 1; - BX_VGA_THIS s.graphics_ctrl.memory_mapping = 1; - BX_VGA_THIS s.CRTC.reg[1] = (BX_VGA_THIS s.vbe_xres / 8) - 1; - BX_VGA_THIS s.CRTC.reg[19] = BX_VGA_THIS s.vbe_xres >> 2; - BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select = 1; - BX_VGA_THIS s.CRTC.reg[18] = (BX_VGA_THIS s.vbe_yres - 1) & 0xff; - BX_VGA_THIS s.CRTC.reg[7] &= ~0x42; - if ((BX_VGA_THIS s.vbe_yres - 1) & 0x0100) { - BX_VGA_THIS s.CRTC.reg[7] |= 0x02; - } - if ((BX_VGA_THIS s.vbe_yres - 1) & 0x0200) { - BX_VGA_THIS s.CRTC.reg[7] |= 0x40; - } - } - } - else - { - if (BX_VGA_THIS s.vbe_enabled) BX_INFO(("VBE disabling")); - BX_VGA_THIS s.vbe_lfb_enabled=0; - } - BX_VGA_THIS s.vbe_enabled=(bx_bool)(value & VBE_DISPI_ENABLED); - } break; - - case VBE_DISPI_INDEX_X_OFFSET: - { - // BX_INFO(("VBE offset x %x",value)); - BX_VGA_THIS s.vbe_offset_x=(Bit16u)value; - - BX_VGA_THIS s.vbe_virtual_start = ((BX_VGA_THIS s.vbe_offset_y) * (BX_VGA_THIS s.vbe_line_byte_width)) + - ((BX_VGA_THIS s.vbe_offset_x) * (BX_VGA_THIS s.vbe_bpp_multiplier)); - - BX_VGA_THIS s.vga_mem_updated = 1; - for (unsigned xti = 0; xti < BX_NUM_X_TILES; xti++) { - for (unsigned yti = 0; yti < BX_NUM_Y_TILES; yti++) { - SET_TILE_UPDATED (xti, yti, 1); - } - } - } break; - - case VBE_DISPI_INDEX_Y_OFFSET: - { - // BX_INFO(("VBE offset y %x",value)); - BX_VGA_THIS s.vbe_offset_y=(Bit16u)value; - BX_VGA_THIS s.vbe_virtual_start = ((BX_VGA_THIS s.vbe_offset_y) * (BX_VGA_THIS s.vbe_line_byte_width)) + - ((BX_VGA_THIS s.vbe_offset_x) * (BX_VGA_THIS s.vbe_bpp_multiplier)); - - BX_VGA_THIS s.vga_mem_updated = 1; - for (unsigned xti = 0; xti < BX_NUM_X_TILES; xti++) { - for (unsigned yti = 0; yti < BX_NUM_Y_TILES; yti++) { - SET_TILE_UPDATED (xti, yti, 1); - } - } - } break; - - case VBE_DISPI_INDEX_VIRT_WIDTH: - { - BX_INFO(("VBE requested virtual width %d",value)); - - // calculate virtual width & height dimensions - // req: - // virt_width > xres - // virt_height >=yres - // virt_width*virt_height < MAX_VIDEO_MEMORY - - // basicly 2 situations - - // situation 1: - // MAX_VIDEO_MEMORY / virt_width >= yres - // adjust result height - // else - // adjust result width based upon virt_height=yres - Bit16u new_width=value; - Bit16u new_height=(sizeof(BX_VGA_THIS s.vbe_memory) / BX_VGA_THIS s.vbe_bpp_multiplier) / new_width; - if (new_height >=BX_VGA_THIS s.vbe_yres) - { - // we have a decent virtual width & new_height - BX_INFO(("VBE decent virtual height %d",new_height)); - } - else - { - // no decent virtual height: adjust width & height - new_height=BX_VGA_THIS s.vbe_yres; - new_width=(sizeof(BX_VGA_THIS s.vbe_memory) / BX_VGA_THIS s.vbe_bpp_multiplier) / new_height; - - BX_INFO(("VBE recalc virtual width %d height %d",new_width, new_height)); - } - - BX_VGA_THIS s.vbe_virtual_xres=new_width; - BX_VGA_THIS s.vbe_virtual_yres=new_height; - BX_VGA_THIS s.vbe_visable_screen_size = (new_width * (BX_VGA_THIS s.vbe_yres)) * BX_VGA_THIS s.vbe_bpp_multiplier; - - } break; - /* - case VBE_DISPI_INDEX_VIRT_HEIGHT: - { - BX_INFO(("VBE virtual height %x",value)); - - } break; - */ - default: - { - BX_PANIC(("VBE unknown data write index 0x%x",BX_VGA_THIS s.vbe_curindex)); - } break; - } - break; - - } // end switch address -} - -#endif diff --git a/tools/ioemu/iodev/vga.h b/tools/ioemu/iodev/vga.h deleted file mode 100644 index cafb60cd6b..0000000000 --- a/tools/ioemu/iodev/vga.h +++ /dev/null @@ -1,300 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: vga.h,v 1.36 2003/12/31 10:33:27 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -#if BX_SUPPORT_VBE - #define VBE_DISPI_TOTAL_VIDEO_MEMORY_MB 4 - - #define VBE_DISPI_BANK_ADDRESS 0xA0000 - #define VBE_DISPI_BANK_SIZE_KB 64 - - #define VBE_DISPI_MAX_XRES 1024 - #define VBE_DISPI_MAX_YRES 768 - - #define VBE_DISPI_IOPORT_INDEX 0x01CE - #define VBE_DISPI_IOPORT_DATA 0x01CF - - #define VBE_DISPI_IOPORT_INDEX_OLD 0xFF80 - #define VBE_DISPI_IOPORT_DATA_OLD 0xFF81 - - #define VBE_DISPI_INDEX_ID 0x0 - #define VBE_DISPI_INDEX_XRES 0x1 - #define VBE_DISPI_INDEX_YRES 0x2 - #define VBE_DISPI_INDEX_BPP 0x3 - #define VBE_DISPI_INDEX_ENABLE 0x4 - #define VBE_DISPI_INDEX_BANK 0x5 - #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 - #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 - #define VBE_DISPI_INDEX_X_OFFSET 0x8 - #define VBE_DISPI_INDEX_Y_OFFSET 0x9 - - #define VBE_DISPI_ID0 0xB0C0 - #define VBE_DISPI_ID1 0xB0C1 - #define VBE_DISPI_ID2 0xB0C2 - - #define VBE_DISPI_BPP_4 0x04 - #define VBE_DISPI_BPP_8 0x08 - #define VBE_DISPI_BPP_15 0x0F - #define VBE_DISPI_BPP_16 0x10 - #define VBE_DISPI_BPP_24 0x18 - #define VBE_DISPI_BPP_32 0x20 - - #define VBE_DISPI_DISABLED 0x00 - #define VBE_DISPI_ENABLED 0x01 - #define VBE_DISPI_NOCLEARMEM 0x80 - #define VBE_DISPI_LFB_ENABLED 0x40 - - #define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 - - -#define VBE_DISPI_TOTAL_VIDEO_MEMORY_KB (VBE_DISPI_TOTAL_VIDEO_MEMORY_MB * 1024) -#define VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES (VBE_DISPI_TOTAL_VIDEO_MEMORY_KB * 1024) - -#define BX_MAX_XRES VBE_DISPI_MAX_XRES -#define BX_MAX_YRES VBE_DISPI_MAX_YRES - -#else - -#define BX_MAX_XRES 800 -#define BX_MAX_YRES 600 - -#endif //BX_SUPPORT_VBE - -#define X_TILESIZE 16 -#define Y_TILESIZE 24 -#define BX_NUM_X_TILES (BX_MAX_XRES /X_TILESIZE) -#define BX_NUM_Y_TILES (BX_MAX_YRES /Y_TILESIZE) - -// Support varying number of rows of text. This used to -// be limited to only 25 lines. -#define BX_MAX_TEXT_LINES 100 - -#if BX_USE_VGA_SMF -# define BX_VGA_SMF static -# define BX_VGA_THIS theVga-> -#else -# define BX_VGA_SMF -# define BX_VGA_THIS this-> -#endif - - -class bx_vga_c : public bx_vga_stub_c { -public: - - bx_vga_c(void); - ~bx_vga_c(void); - virtual void init(void); - virtual void bios_init(void); - virtual void reset(unsigned type); - virtual Bit8u mem_read(Bit32u addr); - // Note: either leave value of type Bit8u, or mask it when - // used to 8 bits, in memory.cc - virtual void mem_write(Bit32u addr, Bit8u value); - virtual void trigger_timer(void *this_ptr); - -#if BX_SUPPORT_VBE - BX_VGA_SMF Bit8u vbe_mem_read(Bit32u addr) BX_CPP_AttrRegparmN(1); - BX_VGA_SMF void vbe_mem_write(Bit32u addr, Bit8u value) BX_CPP_AttrRegparmN(2); -#endif - - virtual void redraw_area(unsigned x0, unsigned y0, - unsigned width, unsigned height); - - virtual void set_update_interval (unsigned interval); - virtual void get_text_snapshot(Bit8u **text_snapshot, unsigned *txHeight, - unsigned *txWidth); - virtual Bit8u get_actl_palette_idx(Bit8u index); - -private: - - static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); - static void write_handler_no_log(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); - -#if BX_SUPPORT_VBE - static Bit32u vbe_read_handler(void *this_ptr, Bit32u address, unsigned io_len); - static void vbe_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); -#endif - - struct { - struct { - bx_bool color_emulation; // 1=color emulation, base address = 3Dx - // 0=mono emulation, base address = 3Bx - bx_bool enable_ram; // enable CPU access to video memory if set - Bit8u clock_select; // 0=25Mhz 1=28Mhz - bx_bool select_high_bank; // when in odd/even modes, select - // high 64k bank if set - bx_bool horiz_sync_pol; // bit6: negative if set - bx_bool vert_sync_pol; // bit7: negative if set - // bit7,bit6 represent number of lines on display: - // 0 = reserved - // 1 = 400 lines - // 2 = 350 lines - // 3 - 480 lines - } misc_output; - - struct { - Bit8u address; - Bit8u reg[0x19]; - } CRTC; - - struct { - bx_bool flip_flop; /* 0 = address, 1 = data-write */ - unsigned address; /* register number */ - bx_bool video_enabled; - Bit8u palette_reg[16]; - Bit8u overscan_color; - Bit8u color_plane_enable; - Bit8u horiz_pel_panning; - Bit8u color_select; - struct { - bx_bool graphics_alpha; - bx_bool display_type; - bx_bool enable_line_graphics; - bx_bool blink_intensity; - bx_bool pixel_panning_compat; - bx_bool pixel_clock_select; - bx_bool internal_palette_size; - } mode_ctrl; - } attribute_ctrl; - - struct { - Bit8u write_data_register; - Bit8u write_data_cycle; /* 0, 1, 2 */ - Bit8u read_data_register; - Bit8u read_data_cycle; /* 0, 1, 2 */ - Bit8u dac_state; - struct { - Bit8u red; - Bit8u green; - Bit8u blue; - } data[256]; - Bit8u mask; - } pel; - - - struct { - Bit8u index; - Bit8u set_reset; - Bit8u enable_set_reset; - Bit8u color_compare; - Bit8u data_rotate; - Bit8u raster_op; - Bit8u read_map_select; - Bit8u write_mode; - bx_bool read_mode; - bx_bool odd_even; - bx_bool chain_odd_even; - Bit8u shift_reg; - bx_bool graphics_alpha; - Bit8u memory_mapping; /* 0 = use A0000-BFFFF - * 1 = use A0000-AFFFF EGA/VGA graphics modes - * 2 = use B0000-B7FFF Monochrome modes - * 3 = use B8000-BFFFF CGA modes - */ - Bit8u color_dont_care; - Bit8u bitmask; - Bit8u latch[4]; - } graphics_ctrl; - - struct { - Bit8u index; - Bit8u map_mask; - bx_bool map_mask_bit[4]; - bx_bool reset1; - bx_bool reset2; - Bit8u reg1; - Bit8u char_map_select; - bx_bool extended_mem; - bx_bool odd_even; - bx_bool chain_four; - } sequencer; - - bx_bool vga_mem_updated; - unsigned x_tilesize; - unsigned y_tilesize; - unsigned line_offset; - unsigned line_compare; - unsigned vertical_display_end; - bx_bool vga_tile_updated[BX_NUM_X_TILES][BX_NUM_Y_TILES]; - Bit8u vga_memory[256 * 1024]; - Bit8u text_snapshot[32 * 1024]; // current text snapshot - Bit8u rgb[3 * 256]; - Bit8u tile[X_TILESIZE * Y_TILESIZE * 4]; /**< Currently allocates the tile as large as needed. */ - Bit16u charmap_address; - bx_bool x_dotclockdiv2; - bx_bool y_doublescan; - -#if BX_SUPPORT_VBE - Bit8u vbe_memory[VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES]; - Bit16u vbe_cur_dispi; - Bit16u vbe_xres; - Bit16u vbe_yres; - Bit16u vbe_bpp; - Bit16u vbe_bank; - bx_bool vbe_enabled; - Bit16u vbe_curindex; - Bit32u vbe_visable_screen_size; /**< in bytes */ - Bit16u vbe_offset_x; /**< Virtual screen x start (in pixels) */ - Bit16u vbe_offset_y; /**< Virtual screen y start (in pixels) */ - Bit16u vbe_virtual_xres; - Bit16u vbe_virtual_yres; - Bit16u vbe_line_byte_width; /**< For dealing with bpp>8, this is they width of a line in bytes. */ - Bit32u vbe_virtual_start; /**< For dealing with bpp>8, this is where the virtual screen starts. */ - Bit8u vbe_bpp_multiplier; /**< We have to save this b/c sometimes we need to recalculate stuff with it. */ - bx_bool vbe_lfb_enabled; -#endif - } s; // state information - - -#if !BX_USE_VGA_SMF - Bit32u read(Bit32u address, unsigned io_len); - void write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log); -#else - void write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log); -#endif - -#if BX_SUPPORT_VBE - -#if !BX_USE_VGA_SMF - Bit32u vbe_read(Bit32u address, unsigned io_len); - void vbe_write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log); -#else - void vbe_write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log); -#endif -#endif - - int timer_id; - - public: - static void timer_handler(void *); - BX_VGA_SMF void timer(void); - - private: - BX_VGA_SMF void update(void); - BX_VGA_SMF void dump_status(void); - BX_VGA_SMF void determine_screen_dimensions(unsigned *piHeight, - unsigned *piWidth); - }; diff --git a/tools/ioemu/iodev/virt_timer.cc b/tools/ioemu/iodev/virt_timer.cc deleted file mode 100644 index eb108a025b..0000000000 --- a/tools/ioemu/iodev/virt_timer.cc +++ /dev/null @@ -1,552 +0,0 @@ -//////////////////////////////////////////////////////////////////////// -// $Id: virt_timer.cc,v 1.19.2.1 2004/02/06 22:14:36 danielg4 Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -///////////////////////////////////////////////////////////////////////// -// -//Realtime Algorithm (with gettimeofday) -// HAVE: -// Real number of usec. -// Emulated number of usec. -// WANT: -// Number of ticks to use. -// Number of emulated usec to wait until next try. -// -// ticks=number of ticks needed to match total real usec. -// if(desired ticks > max ticks for elapsed real time) -// ticks = max ticks for elapsed real time. -// if(desired ticks > max ticks for elapsed emulated usec) -// ticks = max ticks for emulated usec. -// next wait ticks = number of ticks until next event. -// next wait real usec = (current ticks + next wait ticks) * usec per ticks -// next wait emulated usec = next wait real usec * emulated usec / real usec -// if(next wait emulated usec < minimum emulated usec for next wait ticks) -// next wait emulated usec = minimum emulated usec for next wait ticks. -// if(next wait emulated usec > max emulated usec wait) -// next wait emulated usec = max emulated usec wait. -// -// How to calculate elapsed real time: -// store an unused time value whenever no ticks are used in a given time. -// add this to the current elapsed time. -// How to calculate elapsed emulated time: -// same as above. -// Above can be done by not updating last_usec and last_sec. -// -// How to calculate emulated usec/real usec: -// Each time there are actual ticks: -// Alpha_product(old emulated usec, emulated usec); -// Alpha_product(old real usec, real usec); -// Divide resulting values. -// -///////////////////////////////////////////////////////////////////////// - -#include "bochs.h" - -#define BX_USE_VIRTUAL_TIMERS 1 -#define BX_VIRTUAL_TIMERS_REALTIME 1 - -//Important constant #defines: -#define USEC_PER_SECOND (1000000) - - -// define a macro to convert floating point numbers into 64-bit integers. -// In MSVC++ you can convert a 64-bit float into a 64-bit signed integer, -// but it will not convert a 64-bit float into a 64-bit unsigned integer. -// This macro works around that. -#define F2I(x) ((Bit64u)(Bit64s) (x)) -#define I2F(x) ((double)(Bit64s) (x)) - -//CONFIGURATION #defines: - - -//MAINLINE Configuration (For realtime PIT): - -//How much faster than real time we can go: -#define MAX_MULT (1.25) - -//Minimum number of emulated useconds per second. -// Now calculated using BX_MIN_IPS, the minimum number of -// instructions per second. -#define MIN_USEC_PER_SECOND (((((Bit64u)USEC_PER_SECOND)*((Bit64u)BX_MIN_IPS))/((Bit64u)(bx_options.Oips->get())))+(Bit64u)1) - - -//DEBUG configuration: - -//Debug with printf options. -#define DEBUG_REALTIME_WITH_PRINTF 0 - -//Use to test execution at multiples of real time. -#define TIME_DIVIDER (1) -#define TIME_MULTIPLIER (1) -#define TIME_HEADSTART (0) - - -#define GET_VIRT_REALTIME64_USEC() (((bx_get_realtime64_usec()*(Bit64u)TIME_MULTIPLIER/(Bit64u)TIME_DIVIDER))) -//Set up Logging. -#define LOG_THIS bx_virt_timer. - -//A single instance. -bx_virt_timer_c bx_virt_timer; - - -//Generic MAX and MIN Functions -#define BX_MAX(a,b) ( ((a)>(b))?(a):(b) ) -#define BX_MIN(a,b) ( ((a)>(b))?(b):(a) ) - - -//USEC_ALPHA is multiplier for the past. -//USEC_ALPHA_B is 1-USEC_ALPHA, or multiplier for the present. -#define USEC_ALPHA ((double)(.8)) -#define USEC_ALPHA_B ((double)(((double)1)-USEC_ALPHA)) -#define USEC_ALPHA2 ((double)(.5)) -#define USEC_ALPHA2_B ((double)(((double)1)-USEC_ALPHA2)) -#define ALPHA_LOWER(old,new) ((Bit64u)((old0); - BX_ASSERT(!in_timer_handler); - - if(last_sequential_time >= current_timers_time) { - periodic(1); - last_sequential_time = current_timers_time; - } - return current_timers_time; -} - - - -//Register a timer handler to go off after a given interval. -//Register a timer handler to go off with a periodic interval. -int -bx_virt_timer_c::register_timer( void *this_ptr, bx_timer_handler_t handler, - Bit32u useconds, - bx_bool continuous, bx_bool active, - const char *id) { - if(!use_virtual_timers) { - return bx_pc_system.register_timer(this_ptr, handler, useconds, - continuous, active, id); - } - - //We don't like starting with a zero period timer. - BX_ASSERT((!active) || (useconds>0)); - - //Search for an unused timer. - unsigned int i; - for (i=0; i < numTimers; i++) { - if (timer[i].inUse == 0 || i==numTimers) - break; - } - // If we didn't find a free slot, increment the bound, numTimers. - if (i==numTimers) - numTimers++; // One new timer installed. - BX_ASSERT(numTimers= 0); - BX_ASSERT(timerID < BX_MAX_VIRTUAL_TIMERS); - - if (timer[timerID].active) { - BX_PANIC(("unregisterTimer: timer '%s' is still active!", timer[timerID].id)); - return(0); // Fail. - } - - - //No need to prevent doing this to unused timers. - timer[timerID].inUse = 0; - return(1); -} - -void -bx_virt_timer_c::start_timers(void) { - if(!use_virtual_timers) { - bx_pc_system.start_timers(); - return; - } - //FIXME -} - -//activate a deactivated but registered timer. -void -bx_virt_timer_c::activate_timer( unsigned timer_index, Bit32u useconds, - bx_bool continuous ) { - if(!use_virtual_timers) { - bx_pc_system.activate_timer(timer_index, useconds, continuous); - return; - } - - BX_ASSERT(timer_index >= 0); - BX_ASSERT(timer_index < BX_MAX_VIRTUAL_TIMERS); - - BX_ASSERT(timer[timer_index].inUse); - BX_ASSERT(useconds>0); - - timer[timer_index].period=useconds; - timer[timer_index].timeToFire = current_timers_time + (Bit64u)useconds; - timer[timer_index].active=1; - timer[timer_index].continuous=continuous; - - if(useconds < timers_next_event_time) { - timers_next_event_time = useconds; - next_event_time_update(); - //FIXME - } -} - -//deactivate (but don't unregister) a currently registered timer. -void -bx_virt_timer_c::deactivate_timer( unsigned timer_index ) { - if(!use_virtual_timers) { - bx_pc_system.deactivate_timer(timer_index); - return; - } - - BX_ASSERT(timer_index >= 0); - BX_ASSERT(timer_index < BX_MAX_VIRTUAL_TIMERS); - - //No need to prevent doing this to unused/inactive timers. - timer[timer_index].active = 0; -} - -void -bx_virt_timer_c::advance_virtual_time(Bit64u time_passed) { - BX_ASSERT(time_passed <= virtual_next_event_time); - - current_virtual_time += time_passed; - virtual_next_event_time -= time_passed; - - if(current_virtual_time > current_timers_time) { - periodic(current_virtual_time - current_timers_time); - } -} - -//Called when next_event_time changes. -void -bx_virt_timer_c::next_event_time_update(void) { - virtual_next_event_time = timers_next_event_time + current_timers_time - current_virtual_time; - if(init_done) { - bx_pc_system.deactivate_timer(system_timer_id); - BX_ASSERT(virtual_next_event_time); - bx_pc_system.activate_timer(system_timer_id, - (Bit32u)BX_MIN(0x7FFFFFFF,BX_MAX(1,TICKS_TO_USEC(virtual_next_event_time))), - 0); - } -} - -void -bx_virt_timer_c::init(void) { - - if ( (bx_options.clock.Osync->get ()!=BX_CLOCK_SYNC_REALTIME) - && (bx_options.clock.Osync->get ()!=BX_CLOCK_SYNC_BOTH) ) - virtual_timers_realtime = 0; - else - virtual_timers_realtime = 1; - - if (virtual_timers_realtime) { - BX_INFO(("using 'realtime pit' synchronization method")); - } - - register_timer(this, nullTimer, (Bit32u)NullTimerInterval, 1, 1, "Null Timer"); - - system_timer_id = bx_pc_system.register_timer(this, pc_system_timer_handler,virtual_next_event_time , 0, 1, "Virtual Timer"); - - //Real time variables: -#if BX_HAVE_REALTIME_USEC - last_real_time=GET_VIRT_REALTIME64_USEC()+(Bit64u)TIME_HEADSTART*(Bit64u)USEC_PER_SECOND; -#endif - total_real_usec=0; - last_realtime_delta=0; - //System time variables: - last_usec = 0 -; - usec_per_second = USEC_PER_SECOND; - stored_delta=0; - last_system_usec=0; - em_last_realtime=0; - //Virtual timer variables: - total_ticks=0; - last_realtime_ticks=0; - ticks_per_second = USEC_PER_SECOND; - - init_done = 1; -} - -void -bx_virt_timer_c::timer_handler(void) { - if(!virtual_timers_realtime) { - Bit64u temp_final_time = bx_pc_system.time_usec(); - temp_final_time-=current_virtual_time; - while(temp_final_time) { - if((temp_final_time)>(virtual_next_event_time)) { - temp_final_time-=virtual_next_event_time; - advance_virtual_time(virtual_next_event_time); - } else { - advance_virtual_time(temp_final_time); - temp_final_time-=temp_final_time; - } - } - bx_pc_system.activate_timer(system_timer_id, - (Bit32u)BX_MIN(0x7FFFFFFF,(virtual_next_event_time>2)?(virtual_next_event_time-2):1), - 0); - return; - } - - Bit64u usec_delta = bx_pc_system.time_usec()-last_usec; - - if (usec_delta) { -#if BX_HAVE_REALTIME_USEC - Bit64u ticks_delta = 0; - Bit64u real_time_delta = GET_VIRT_REALTIME64_USEC() - last_real_time; - Bit64u real_time_total = real_time_delta + total_real_usec; - Bit64u system_time_delta = (Bit64u)usec_delta + (Bit64u)stored_delta; - if(real_time_delta) { - last_realtime_delta = real_time_delta; - last_realtime_ticks = total_ticks; - } - ticks_per_second = USEC_PER_SECOND; - - //Start out with the number of ticks we would like - // to have to line up with real time. - ticks_delta = real_time_total - total_ticks; - if(real_time_total < total_ticks) { - //This slows us down if we're already ahead. - // probably only an issue on startup, but it solves some problems. - ticks_delta = 0; - } - if(ticks_delta + total_ticks - last_realtime_ticks > (F2I(MAX_MULT * I2F(last_realtime_delta)))) { - //This keeps us from going too fast in relation to real time. -#if 0 - ticks_delta = (F2I(MAX_MULT * I2F(last_realtime_delta))) + last_realtime_ticks - total_ticks; -#endif - ticks_per_second = F2I(MAX_MULT * I2F(USEC_PER_SECOND)); - } - if(ticks_delta > system_time_delta * USEC_PER_SECOND / MIN_USEC_PER_SECOND) { - //This keeps us from having too few instructions between ticks. - ticks_delta = system_time_delta * USEC_PER_SECOND / MIN_USEC_PER_SECOND; - } - if(ticks_delta > virtual_next_event_time) { - //This keeps us from missing ticks. - ticks_delta = virtual_next_event_time; - } - - if(ticks_delta) { - -# if DEBUG_REALTIME_WITH_PRINTF - //Every second print some info. - if(((last_real_time + real_time_delta) / USEC_PER_SECOND) > (last_real_time / USEC_PER_SECOND)) { - Bit64u temp1, temp2, temp3, temp4; - temp1 = (Bit64u) total_real_usec; - temp2 = (total_real_usec); - temp3 = (Bit64u)total_ticks; - temp4 = (Bit64u)((total_real_usec) - total_ticks); - printf("useconds: %llu, ",temp1); - printf("expect ticks: %llu, ",temp2); - printf("ticks: %llu, ",temp3); - printf("diff: %llu\n",temp4); - } -# endif - - last_real_time += real_time_delta; - total_real_usec += real_time_delta; - last_system_usec += system_time_delta; - stored_delta = 0; - total_ticks += ticks_delta; - } else { - stored_delta = system_time_delta; - } - - - Bit64u a,b; - a=(usec_per_second); - if(real_time_delta) { - //FIXME - Bit64u em_realtime_delta = last_system_usec + stored_delta - em_last_realtime; - b=((Bit64u)USEC_PER_SECOND * em_realtime_delta / real_time_delta); - em_last_realtime = last_system_usec + stored_delta; - } else { - b=a; - } - usec_per_second = ALPHA_LOWER(a,b); -#else - BX_ASSERT(0); -#endif -#if BX_HAVE_REALTIME_USEC - advance_virtual_time(ticks_delta); -#endif - } - - last_usec=last_usec + usec_delta; - bx_pc_system.deactivate_timer(system_timer_id); - BX_ASSERT(virtual_next_event_time); - bx_pc_system.activate_timer(system_timer_id, - (Bit32u)BX_MIN(0x7FFFFFFF,BX_MAX(1,TICKS_TO_USEC(virtual_next_event_time))), - 0); - -} - -void -bx_virt_timer_c::pc_system_timer_handler(void* this_ptr) { - ((bx_virt_timer_c *)this_ptr)->timer_handler(); -} - diff --git a/tools/ioemu/iodev/virt_timer.h b/tools/ioemu/iodev/virt_timer.h deleted file mode 100644 index a10b16cd0e..0000000000 --- a/tools/ioemu/iodev/virt_timer.h +++ /dev/null @@ -1,131 +0,0 @@ - -#ifndef _BX_VIRT_TIMER_H -#define _BX_VIRT_TIMER_H - - -#define BX_MAX_VIRTUAL_TIMERS (15+BX_SMP_PROCESSORS) -#define BX_NULL_VIRTUAL_TIMER_HANDLE 10000 - -#define BX_MAX_VIRTUAL_TIME (0x7fffffff) - -class bx_virt_timer_c : public logfunctions { - private: - - struct { - bx_bool inUse; // Timer slot is in-use (currently registered). - Bit64u period; // Timer periodocity in virtual useconds. - Bit64u timeToFire; // Time to fire next (in virtual useconds). - bx_bool active; // 0=inactive, 1=active. - bx_bool continuous; // 0=one-shot timer, 1=continuous periodicity. - bx_timer_handler_t funct; // A callback function for when the - // timer fires. - // This function MUST return. - void *this_ptr; // The this-> pointer for C++ callbacks - // has to be stored as well. - char id[BxMaxTimerIDLen]; // String ID of timer. - } timer[BX_MAX_VIRTUAL_TIMERS]; - - unsigned numTimers; // Number of currently allocated timers. - - //Variables for the timer subsystem: - Bit64u current_timers_time; - Bit64u timers_next_event_time; - - Bit64u last_sequential_time; - bx_bool in_timer_handler; - - //Variables for the time sync subsystem: - Bit64u virtual_next_event_time; - Bit64u current_virtual_time; - - //Real time variables: - Bit64u last_real_time; - Bit64u total_real_usec; - Bit64u last_realtime_delta; - //System time variables: - Bit64u last_usec; - Bit64u usec_per_second; - Bit64u stored_delta; - Bit64u last_system_usec; - Bit64u em_last_realtime; - //Virtual timer variables: - Bit64u total_ticks; - Bit64u last_realtime_ticks; - Bit64u ticks_per_second; - - bx_bool init_done; - - int system_timer_id; - - //Whether or not to use virtual timers. - bx_bool use_virtual_timers; - bx_bool virtual_timers_realtime; - - // A special null timer is always inserted in the timer[0] slot. This - // make sure that at least one timer is always active, and that the - // duration is always less than a maximum 32-bit integer, so a 32-bit - // counter can be used for the current countdown. - static const Bit64u NullTimerInterval; - static void nullTimer(void* this_ptr); - - - //Step the given number of cycles, optionally calling any timer handlers. - void periodic(Bit64u time_passed); - - - //Called when next_event_time changes. - void next_event_time_update(void); - - //Called to advance the virtual time. - // calls periodic as needed. - void advance_virtual_time(Bit64u time_passed); - - public: - - - //Get the current virtual time. - // This may return the same value on subsequent calls. - Bit64u time_usec(void); - - //Get the current virtual time. - // This will return a monotonically increasing value. - // MUST NOT be called from within a timer handler. - Bit64u time_usec_sequential(void); - - //Register a timer handler to go off after a given interval. - //Register a timer handler to go off with a periodic interval. - int register_timer( void *this_ptr, bx_timer_handler_t handler, - Bit32u useconds, - bx_bool continuous, bx_bool active, const char *id); - - //unregister a previously registered timer. - unsigned unregisterTimer(int timerID); - - void start_timers(void); - - //activate a deactivated but registered timer. - void activate_timer( unsigned timer_index, Bit32u useconds, - bx_bool continuous ); - - //deactivate (but don't unregister) a currently registered timer. - void deactivate_timer( unsigned timer_index ); - - - //Timer handler passed to pc_system - static void pc_system_timer_handler(void* this_ptr); - - //The real timer handler. - void timer_handler(); - - //Initialization - void init(void); - bx_virt_timer_c(void); - ~bx_virt_timer_c(void); - -}; - - - -extern bx_virt_timer_c bx_virt_timer; - -#endif // _BX_VIRT_TIMER_H diff --git a/tools/ioemu/keyboard_rdesktop.c b/tools/ioemu/keyboard_rdesktop.c new file mode 100644 index 0000000000..a98df10149 --- /dev/null +++ b/tools/ioemu/keyboard_rdesktop.c @@ -0,0 +1,165 @@ +/* + * QEMU keylayout reader: read rdesktop style keylaouts + * + * Copyright (c) 2004,2005 Johannes E. Schindelin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include + +#ifdef KEYBOARD_IGNORE_CASE +#define STRCMP strcasecmp +#else +#define STRCMP strcmp +#endif + +/* binary search through nameToKeysym */ +static int get_keysym(const char* name) +{ + int i1=-1,i2=sizeof(name2keysym)/sizeof(name2keysym_t),i3=i2/2,r; + while((r=STRCMP(name,name2keysym[i3].name))!=0) { + if(r<0) + i2=i3; + else + i1=i3; + i3=(i1+i2)/2; + if(i2-i1<2) + return 0; + } + return name2keysym[i3].keysym; +} + +typedef unsigned short WORD; +#define MAX_NORMAL_KEYCODE 512 +#define MAX_EXTRA_COUNT 256 +typedef struct { + WORD keysym2keycode[MAX_NORMAL_KEYCODE]; + struct { + int keysym; + WORD keycode; + } keysym2keycode_extra[MAX_EXTRA_COUNT]; + int extra_count; +} kbd_layout_t; + +static int parse_int(const char* text) +{ + if(!strncmp(text,"0x",2)) { + int result=0; + sscanf(text+2,"%x",&result); + return result; + } + return atoi(text); +} + +static kbd_layout_t* parse_keyboard_layout(const char* language,kbd_layout_t* k) +{ + FILE* f; + const char* prefix="/keymaps/"; + char* file_name=malloc(strlen(prefix)+strlen(language)+strlen(bios_dir)+1); + + if(!k) + k=calloc(sizeof(kbd_layout_t),1); + strcpy(file_name,bios_dir); + strcat(file_name,prefix); + strcat(file_name,language); + if(file_name[strlen(file_name)-1]=='\n') + file_name[strlen(file_name)-1]=0; + if(!(f=fopen(file_name,"r"))) { + term_printf("Warning: could not read keymap - falling back native keycodes!\n"); + free(file_name); + return 0; + } + free(file_name); + while(!feof(f)) { + char line[1024]; + fgets(line,1024,f); + if(line[0]=='#') + continue; + if(!strncmp(line,"map ",4)) + continue; + if(!strncmp(line,"include ",8)) + parse_keyboard_layout(line+8,k); + else { + char* end_of_keysym=line; + while(*end_of_keysym!=0 && *end_of_keysym!=' ') + end_of_keysym++; + if(*end_of_keysym) { + int keysym; + *end_of_keysym=0; + keysym=get_keysym(line); + if(keysym==0) { + term_printf("Warning: 1unknown keysym %s\n",line); + } else { + const char* rest=end_of_keysym+1; + int keycode=parse_int(rest); + /* if(keycode&0x80) + keycode=(keycode<<8)^0x80e0; */ + if(keysymkeysym2keycode[keysym]=keycode; +#ifndef KEYBOARD_IGNORE_CASE + line[0]=toupper(line[0]); + keysym=get_keysym(line); + if(keysym) + k->keysym2keycode[keysym]=keycode; +#endif + } else { + if(k->extra_count>=MAX_EXTRA_COUNT) { + term_printf("Warning: Could not assign keysym %s (0x%x) because of memory constraints.\n",line,keysym); + } else { + //term_printf("Setting %d: %d,%d\n",k->extra_count,keysym,keycode); + k->keysym2keycode_extra[k->extra_count].keysym=keysym; + k->keysym2keycode_extra[k->extra_count].keycode=keycode; + k->extra_count++; + } + } + } + } + } + } + fclose(f); + return k; +} + +static void* init_keyboard_layout(const char* language) +{ + return parse_keyboard_layout(language,0); +} + +static WORD keysym2scancode(void* kbd_layout, int keysym) +{ + kbd_layout_t* k=kbd_layout; + if(keysymkeysym2keycode[keysym]==0) + term_printf("Warning: no scancode found for keysym %d\n",keysym); + return k->keysym2keycode[keysym]; + } else { + int i; +#ifdef XK_ISO_Left_Tab + if(keysym==XK_ISO_Left_Tab) + keysym=XK_Tab; +#endif + for(i=0;iextra_count;i++) + if(k->keysym2keycode_extra[i].keysym==keysym) + return k->keysym2keycode_extra[i].keycode; + } + return 0; +} + diff --git a/tools/ioemu/keymaps/ar b/tools/ioemu/keymaps/ar new file mode 100644 index 0000000000..c430c03bb3 --- /dev/null +++ b/tools/ioemu/keymaps/ar @@ -0,0 +1,98 @@ +# generated from XKB map ar +include common +map 0x401 +exclam 0x02 shift +at 0x03 shift +numbersign 0x04 shift +dollar 0x05 shift +percent 0x06 shift +asciicircum 0x07 shift +ampersand 0x08 shift +asterisk 0x09 shift +parenleft 0x0a shift +parenright 0x0b shift +minus 0x0c +underscore 0x0c shift +equal 0x0d +plus 0x0d shift +Arabic_dad 0x10 altgr +Arabic_fatha 0x10 shift altgr +Arabic_sad 0x11 altgr +Arabic_fathatan 0x11 shift altgr +Arabic_theh 0x12 altgr +Arabic_damma 0x12 shift altgr +Arabic_qaf 0x13 altgr +Arabic_dammatan 0x13 shift altgr +Arabic_feh 0x14 altgr +UFEF9 0x14 shift altgr +Arabic_ghain 0x15 altgr +Arabic_hamzaunderalef 0x15 shift altgr +Arabic_ain 0x16 altgr +grave 0x16 shift altgr +Arabic_ha 0x17 altgr +division 0x17 shift altgr +Arabic_khah 0x18 altgr +multiply 0x18 shift altgr +Arabic_hah 0x19 altgr +Arabic_semicolon 0x19 shift altgr +bracketleft 0x1a +braceleft 0x1a shift +Arabic_jeem 0x1a altgr +bracketright 0x1b +braceright 0x1b shift +Arabic_dal 0x1b altgr +Arabic_sheen 0x1e altgr +backslash 0x1e shift altgr +Arabic_seen 0x1f altgr +Arabic_yeh 0x20 altgr +bracketleft 0x20 shift altgr +Arabic_beh 0x21 altgr +bracketright 0x21 shift altgr +Arabic_lam 0x22 altgr +UFEF7 0x22 shift altgr +Arabic_alef 0x23 altgr +Arabic_hamzaonalef 0x23 shift altgr +Arabic_teh 0x24 altgr +Arabic_tatweel 0x24 shift altgr +Arabic_noon 0x25 altgr +Arabic_comma 0x25 shift altgr +Arabic_meem 0x26 altgr +slash 0x26 shift altgr +semicolon 0x27 +colon 0x27 shift +Arabic_kaf 0x27 altgr +apostrophe 0x28 +quotedbl 0x28 shift +Arabic_tah 0x28 altgr +grave 0x29 +asciitilde 0x29 shift +Arabic_thal 0x29 altgr +Arabic_shadda 0x29 shift altgr +backslash 0x2b +bar 0x2b shift +less 0x2b altgr +greater 0x2b shift altgr +Arabic_hamzaonyeh 0x2c altgr +asciitilde 0x2c shift altgr +Arabic_hamza 0x2d altgr +Arabic_sukun 0x2d shift altgr +Arabic_hamzaonwaw 0x2e altgr +Arabic_kasra 0x2e shift altgr +Arabic_ra 0x2f altgr +Arabic_kasratan 0x2f shift altgr +UFEFB 0x30 altgr +UFEF5 0x30 shift altgr +Arabic_alefmaksura 0x31 altgr +Arabic_maddaonalef 0x31 shift altgr +Arabic_tehmarbuta 0x32 altgr +apostrophe 0x32 shift altgr +comma 0x33 +less 0x33 shift +Arabic_waw 0x33 altgr +period 0x34 +greater 0x34 shift +Arabic_zain 0x34 altgr +slash 0x35 +question 0x35 shift +Arabic_zah 0x35 altgr +Arabic_question_mark 0x35 shift altgr diff --git a/tools/ioemu/keymaps/common b/tools/ioemu/keymaps/common new file mode 100644 index 0000000000..0b53f1c254 --- /dev/null +++ b/tools/ioemu/keymaps/common @@ -0,0 +1,157 @@ +include modifiers + +# +# Top row +# +1 0x2 +2 0x3 +3 0x4 +4 0x5 +5 0x6 +6 0x7 +7 0x8 +8 0x9 +9 0xa +0 0xb +BackSpace 0xe + +# +# QWERTY first row +# +Tab 0xf localstate +ISO_Left_Tab 0xf shift +q 0x10 addupper +w 0x11 addupper +e 0x12 addupper +r 0x13 addupper +t 0x14 addupper +y 0x15 addupper +u 0x16 addupper +i 0x17 addupper +o 0x18 addupper +p 0x19 addupper + +# +# QWERTY second row +# +a 0x1e addupper +s 0x1f addupper +d 0x20 addupper +f 0x21 addupper +g 0x22 addupper +h 0x23 addupper +j 0x24 addupper +k 0x25 addupper +l 0x26 addupper +Return 0x1c localstate + +# +# QWERTY third row +# +z 0x2c addupper +x 0x2d addupper +c 0x2e addupper +v 0x2f addupper +b 0x30 addupper +n 0x31 addupper +m 0x32 addupper + +space 0x39 localstate + +less 0x56 +greater 0x56 shift +bar 0x56 altgr +brokenbar 0x56 shift altgr + +# +# Esc and Function keys +# +Escape 0x1 localstate +F1 0x3b localstate +F2 0x3c localstate +F3 0x3d localstate +F4 0x3e localstate +F5 0x3f localstate +F6 0x40 localstate +F7 0x41 localstate +F8 0x42 localstate +F9 0x43 localstate +F10 0x44 localstate +F11 0x57 localstate +F12 0x58 localstate + +# Printscreen, Scrollock and Pause +# Printscreen really requires four scancodes (0xe0, 0x2a, 0xe0, 0x37), +# but (0xe0, 0x37) seems to work. +Print 0xb7 localstate +Sys_Req 0xb7 localstate +Execute 0xb7 localstate +Scroll_Lock 0x46 + +# +# Insert - PgDown +# +Insert 0xd2 localstate +Delete 0xd3 localstate +Home 0xc7 localstate +End 0xcf localstate +Page_Up 0xc9 localstate +Page_Down 0xd1 localstate + +# +# Arrow keys +# +Left 0xcb localstate +Up 0xc8 localstate +Down 0xd0 localstate +Right 0xcd localstate + +# +# Numpad +# +Num_Lock 0x45 +KP_Divide 0xb5 +KP_Multiply 0x37 +KP_Subtract 0x4a +KP_Add 0x4e +KP_Enter 0x9c + +KP_Decimal 0x53 numlock +KP_Separator 0x53 numlock +KP_Delete 0x53 + +KP_0 0x52 numlock +KP_Insert 0x52 + +KP_1 0x4f numlock +KP_End 0x4f + +KP_2 0x50 numlock +KP_Down 0x50 + +KP_3 0x51 numlock +KP_Next 0x51 + +KP_4 0x4b numlock +KP_Left 0x4b + +KP_5 0x4c numlock +KP_Begin 0x4c + +KP_6 0x4d numlock +KP_Right 0x4d + +KP_7 0x47 numlock +KP_Home 0x47 + +KP_8 0x48 numlock +KP_Up 0x48 + +KP_9 0x49 numlock +KP_Prior 0x49 + +Caps_Lock 0x3a +# +# Inhibited keys +# +Multi_key 0x0 inhibit diff --git a/tools/ioemu/keymaps/convert-map b/tools/ioemu/keymaps/convert-map new file mode 100644 index 0000000000..889b70338d --- /dev/null +++ b/tools/ioemu/keymaps/convert-map @@ -0,0 +1,63 @@ +#!/usr/bin/env python2 +# -*-Python-*- +# +# +# Copyright (C) 2001 Peter Åstrand +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +import sys + +def main(): + f = open(sys.argv[1]) + while 1: + line = f.readline() + if not line: break + + if line.startswith("#") or line.startswith("include"): + print line, + continue + + fields = line.split() + + if line.startswith("map"): + print "map 0x%s" % fields[1] + continue + + scancode = fields[0] + for pos in range(1, len(fields)): + keysym = fields[pos] + + if pos == 1: + modifiers = "" + elif pos == 2: + modifiers = "shift" + elif pos == 3: + modifiers = "altgr" + elif pos == 4: + modifiers = "shift altgr" + else: + raise("Invalid line: %s" % line) + + print "%s 0x%s %s" % (keysym, scancode, modifiers) + + + +if __name__ == "__main__": + if len(sys.argv) < 2: + print "Convert old-style keymaps to new style" + print "Usage: %s " % sys.argv[0] + sys.exit(1) + else: + main() diff --git a/tools/ioemu/keymaps/da b/tools/ioemu/keymaps/da new file mode 100644 index 0000000000..3884dcf145 --- /dev/null +++ b/tools/ioemu/keymaps/da @@ -0,0 +1,120 @@ +# generated from XKB map dk +include common +map 0x406 +exclam 0x02 shift +exclamdown 0x02 altgr +onesuperior 0x02 shift altgr +quotedbl 0x03 shift +at 0x03 altgr +twosuperior 0x03 shift altgr +numbersign 0x04 shift +sterling 0x04 altgr +threesuperior 0x04 shift altgr +currency 0x05 shift +dollar 0x05 altgr +onequarter 0x05 shift altgr +percent 0x06 shift +onehalf 0x06 altgr +cent 0x06 shift altgr +ampersand 0x07 shift +yen 0x07 altgr +fiveeighths 0x07 shift altgr +slash 0x08 shift +braceleft 0x08 altgr +division 0x08 shift altgr +parenleft 0x09 shift +bracketleft 0x09 altgr +guillemotleft 0x09 shift altgr +parenright 0x0a shift +bracketright 0x0a altgr +guillemotright 0x0a shift altgr +equal 0x0b shift +braceright 0x0b altgr +degree 0x0b shift altgr +plus 0x0c +question 0x0c shift +plusminus 0x0c altgr +questiondown 0x0c shift altgr +dead_acute 0x0d +dead_grave 0x0d shift +bar 0x0d altgr +brokenbar 0x0d shift altgr +Greek_OMEGA 0x10 shift altgr +lstroke 0x11 altgr +Lstroke 0x11 shift altgr +EuroSign 0x12 altgr +cent 0x12 shift altgr +registered 0x13 altgr +thorn 0x14 altgr +THORN 0x14 shift altgr +leftarrow 0x15 altgr +yen 0x15 shift altgr +downarrow 0x16 altgr +uparrow 0x16 shift altgr +rightarrow 0x17 altgr +idotless 0x17 shift altgr +oe 0x18 altgr +OE 0x18 shift altgr +thorn 0x19 altgr +THORN 0x19 shift altgr +aring 0x1a +Aring 0x1a shift +dead_diaeresis 0x1a altgr +dead_abovering 0x1a shift altgr +dead_diaeresis 0x1b +dead_circumflex 0x1b shift +dead_tilde 0x1b altgr +dead_caron 0x1b shift altgr +ordfeminine 0x1e altgr +masculine 0x1e shift altgr +ssharp 0x1f altgr +section 0x1f shift altgr +eth 0x20 altgr +ETH 0x20 shift altgr +dstroke 0x21 altgr +ordfeminine 0x21 shift altgr +eng 0x22 altgr +ENG 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +kra 0x25 altgr +lstroke 0x26 altgr +Lstroke 0x26 shift altgr +ae 0x27 +AE 0x27 shift +oslash 0x28 +Ooblique 0x28 shift +dead_caron 0x28 shift altgr +onehalf 0x29 +section 0x29 shift +threequarters 0x29 altgr +paragraph 0x29 shift altgr +apostrophe 0x2b +asterisk 0x2b shift +dead_doubleacute 0x2b altgr +multiply 0x2b shift altgr +guillemotleft 0x2c altgr +guillemotright 0x2d altgr +copyright 0x2e altgr +leftdoublequotemark 0x2f altgr +grave 0x2f shift altgr +rightdoublequotemark 0x30 altgr +mu 0x32 altgr +masculine 0x32 shift altgr +comma 0x33 +semicolon 0x33 shift +dead_cedilla 0x33 altgr +dead_ogonek 0x33 shift altgr +period 0x34 +colon 0x34 shift +periodcentered 0x34 altgr +dead_abovedot 0x34 shift altgr +minus 0x35 +underscore 0x35 shift +hyphen 0x35 altgr +macron 0x35 shift altgr +nobreakspace 0x39 altgr +less 0x56 +greater 0x56 shift +backslash 0x56 altgr +notsign 0x56 shift altgr diff --git a/tools/ioemu/keymaps/de b/tools/ioemu/keymaps/de new file mode 100644 index 0000000000..ed929c743b --- /dev/null +++ b/tools/ioemu/keymaps/de @@ -0,0 +1,114 @@ +# generated from XKB map de +include common +map 0x407 +exclam 0x02 shift +onesuperior 0x02 altgr +exclamdown 0x02 shift altgr +quotedbl 0x03 shift +twosuperior 0x03 altgr +oneeighth 0x03 shift altgr +section 0x04 shift +threesuperior 0x04 altgr +sterling 0x04 shift altgr +dollar 0x05 shift +onequarter 0x05 altgr +currency 0x05 shift altgr +percent 0x06 shift +onehalf 0x06 altgr +threeeighths 0x06 shift altgr +ampersand 0x07 shift +threequarters 0x07 altgr +fiveeighths 0x07 shift altgr +slash 0x08 shift +braceleft 0x08 altgr +seveneighths 0x08 shift altgr +parenleft 0x09 shift +bracketleft 0x09 altgr +trademark 0x09 shift altgr +parenright 0x0a shift +bracketright 0x0a altgr +plusminus 0x0a shift altgr +equal 0x0b shift +braceright 0x0b altgr +ssharp 0x0c +question 0x0c shift +backslash 0x0c altgr +questiondown 0x0c shift altgr +acute 0x0d +dead_acute 0x0d +grave 0x0d shift +dead_grave 0x0d shift +dead_cedilla 0x0d altgr +dead_ogonek 0x0d shift altgr +at 0x10 altgr +Greek_OMEGA 0x10 shift altgr +EuroSign 0x12 altgr +paragraph 0x13 altgr +registered 0x13 shift altgr +tslash 0x14 altgr +Tslash 0x14 shift altgr +z 0x15 addupper +leftarrow 0x15 altgr +yen 0x15 shift altgr +downarrow 0x16 altgr +uparrow 0x16 shift altgr +rightarrow 0x17 altgr +idotless 0x17 shift altgr +oslash 0x18 altgr +Ooblique 0x18 shift altgr +thorn 0x19 altgr +THORN 0x19 shift altgr +udiaeresis 0x1a +Udiaeresis 0x1a shift +dead_diaeresis 0x1a altgr +dead_abovering 0x1a shift altgr +plus 0x1b +asterisk 0x1b shift +asciitilde 0x1b altgr +dead_tilde 0x1b altgr +dead_macron 0x1b shift altgr +ae 0x1e altgr +AE 0x1e shift altgr +eth 0x20 altgr +ETH 0x20 shift altgr +dstroke 0x21 altgr +ordfeminine 0x21 shift altgr +eng 0x22 altgr +ENG 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +kra 0x25 altgr +odiaeresis 0x27 +Odiaeresis 0x27 shift +dead_doubleacute 0x27 altgr +adiaeresis 0x28 +Adiaeresis 0x28 shift +dead_caron 0x28 shift altgr +asciicircum 0x29 +dead_circumflex 0x29 +degree 0x29 shift +notsign 0x29 altgr +numbersign 0x2b +apostrophe 0x2b shift +dead_breve 0x2b shift altgr +y 0x2c addupper +guillemotleft 0x2c altgr +guillemotright 0x2d altgr +cent 0x2e altgr +copyright 0x2e shift altgr +leftdoublequotemark 0x2f altgr +rightdoublequotemark 0x30 altgr +mu 0x32 altgr +masculine 0x32 shift altgr +comma 0x33 +semicolon 0x33 shift +horizconnector 0x33 altgr +multiply 0x33 shift altgr +period 0x34 +colon 0x34 shift +periodcentered 0x34 altgr +division 0x34 shift altgr +minus 0x35 +underscore 0x35 shift +dead_belowdot 0x35 altgr +dead_abovedot 0x35 shift altgr diff --git a/tools/ioemu/keymaps/de-ch b/tools/ioemu/keymaps/de-ch new file mode 100644 index 0000000000..f83837b444 --- /dev/null +++ b/tools/ioemu/keymaps/de-ch @@ -0,0 +1,169 @@ +# rdesktop Swiss-German (de-ch) keymap file +# 2003-06-03 by noldi@tristar.ch +# +include common +map 0x00000807 +# +# Scan Code 1 +section 0x29 +degree 0x29 shift +notsign 0x29 altgr inhibit +# +# Scan Code 2 +plus 0x2 shift +brokenbar 0x02 altgr +# +# Scan Code 3 +quotedbl 0x03 shift +at 0x03 altgr +# +# Scan Code 4 +asterisk 0x04 shift +numbersign 0x04 altgr +# +# Scan Code 5 +ccedilla 0x05 shift +onequarter 0x05 altgr inhibit +# +# Scan Code 6 +percent 0x06 shift +onehalf 0x06 altgr inhibit +# +# Scan Code 7 +ampersand 0x07 shift +notsign 0x07 altgr +# +# Scan Code 8 +slash 0x08 shift +bar 0x08 altgr +# +# Scan Code 9 +parenleft 0x09 shift +cent 0x09 altgr +# +# Scan Code 10 +parenright 0x0a shift +# +# Scan Code 11 +equal 0x0b shift +braceright 0x0b altgr inhibit +# +# Scan Code 12 +apostrophe 0x0c +question 0x0c shift +dead_acute 0x0c altgr +# +# Scan Code 13 +dead_circumflex 0x0d +dead_grave 0x0d shift +dead_tilde 0x0d altgr +# +# Scan Code 19 +EuroSign 0x12 altgr +# +# Scan Code 22 +z 0x15 addupper +# +# Scan Code 27 +udiaeresis 0x1a +egrave 0x1a shift +bracketleft 0x1a altgr +# +# Scan Code 28 +dead_diaeresis 0x1b +exclam 0x1b shift +bracketright 0x1b altgr +# +# Scan Code 40 +odiaeresis 0x27 +eacute 0x27 shift +# +# Scan Code 41 +adiaeresis 0x28 +agrave 0x28 shift +braceleft 0x28 altgr +# +# Scan Code 42 (only on international keyboards) +dollar 0x2b +sterling 0x2b shift +braceright 0x2b altgr +# +# Scan Code 45 (only on international keyboards) +backslash 0x56 altgr +# +# Scan Code 46 +y 0x2c addupper +# +# Scan Code 53 +comma 0x33 +semicolon 0x33 shift +# +# Scan Code 54 +period 0x34 +colon 0x34 shift +# +# Scan Code 55 +minus 0x35 +underscore 0x35 shift +# +# Suppress Windows unsupported AltGr keys +# +# Scan Code 17 +paragraph 0x10 altgr inhibit +# +# Scan Code 21 +tslash 0x14 altgr inhibit +# +# Scan Code 22 +leftarrow 0x15 altgr inhibit +# +# Scan Code 23 +downarrow 0x16 altgr inhibit +# +# Scan Code 24 +rightarrow 0x17 altgr inhibit +# +# Scan Code 25 +oslash 0x18 altgr inhibit +# +# Scan Code 26 +thorn 0x19 altgr inhibit +# +# Scan Code 31 +ae 0x1e altgr inhibit +# +# Scan Code 32 +ssharp 0x1f altgr inhibit +# +# Scan Code 33 +eth 0x20 altgr inhibit +# +# Scan Code 34 +dstroke 0x21 altgr inhibit +# +# Scan Code 35 +eng 0x22 altgr inhibit +# +# Scan Code 36 +hstroke 0x23 altgr inhibit +# +# Scan Code 38 +kra 0x25 altgr inhibit +# +# Scan Code 39 +lstroke 0x26 altgr inhibit +# +# Scan Code 46 +guillemotleft 0x2c altgr inhibit +# +# Scan Code 47 +guillemotright 0x2d altgr inhibit +# +# Scan Code 49 +leftdoublequotemark 0x2f altgr inhibit +# +# Scan Code 50 +rightdoublequotemark 0x30 altgr inhibit +# +# Scan Code 52 +mu 0x32 altgr inhibit diff --git a/tools/ioemu/keymaps/en-gb b/tools/ioemu/keymaps/en-gb new file mode 100644 index 0000000000..b45f06c7ce --- /dev/null +++ b/tools/ioemu/keymaps/en-gb @@ -0,0 +1,119 @@ +# generated from XKB map gb +include common +map 0x809 +exclam 0x02 shift +onesuperior 0x02 altgr +exclamdown 0x02 shift altgr +quotedbl 0x03 shift +twosuperior 0x03 altgr +oneeighth 0x03 shift altgr +sterling 0x04 shift +threesuperior 0x04 altgr +dollar 0x05 shift +EuroSign 0x05 altgr +percent 0x06 shift +onehalf 0x06 altgr +threeeighths 0x06 shift altgr +asciicircum 0x07 shift +threequarters 0x07 altgr +fiveeighths 0x07 shift altgr +ampersand 0x08 shift +braceleft 0x08 altgr +seveneighths 0x08 shift altgr +asterisk 0x09 shift +bracketleft 0x09 altgr +trademark 0x09 shift altgr +parenleft 0x0a shift +bracketright 0x0a altgr +plusminus 0x0a shift altgr +parenright 0x0b shift +braceright 0x0b altgr +degree 0x0b shift altgr +minus 0x0c +underscore 0x0c shift +backslash 0x0c altgr +questiondown 0x0c shift altgr +equal 0x0d +plus 0x0d shift +dead_cedilla 0x0d altgr +dead_ogonek 0x0d shift altgr +at 0x10 altgr +Greek_OMEGA 0x10 shift altgr +lstroke 0x11 altgr +Lstroke 0x11 shift altgr +paragraph 0x13 altgr +registered 0x13 shift altgr +tslash 0x14 altgr +Tslash 0x14 shift altgr +leftarrow 0x15 altgr +yen 0x15 shift altgr +downarrow 0x16 altgr +uparrow 0x16 shift altgr +rightarrow 0x17 altgr +idotless 0x17 shift altgr +oslash 0x18 altgr +Ooblique 0x18 shift altgr +thorn 0x19 altgr +THORN 0x19 shift altgr +bracketleft 0x1a +braceleft 0x1a shift +dead_diaeresis 0x1a altgr +dead_abovering 0x1a shift altgr +bracketright 0x1b +braceright 0x1b shift +dead_tilde 0x1b altgr +dead_macron 0x1b shift altgr +ae 0x1e altgr +AE 0x1e shift altgr +ssharp 0x1f altgr +section 0x1f shift altgr +eth 0x20 altgr +ETH 0x20 shift altgr +dstroke 0x21 altgr +ordfeminine 0x21 shift altgr +eng 0x22 altgr +ENG 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +kra 0x25 altgr +lstroke 0x26 altgr +Lstroke 0x26 shift altgr +semicolon 0x27 +colon 0x27 shift +dead_acute 0x27 altgr +dead_doubleacute 0x27 shift altgr +apostrophe 0x28 +at 0x28 shift +dead_circumflex 0x28 altgr +dead_caron 0x28 shift altgr +grave 0x29 +notsign 0x29 shift +bar 0x29 altgr +numbersign 0x2b +asciitilde 0x2b shift +dead_grave 0x2b altgr +dead_breve 0x2b shift altgr +guillemotleft 0x2c altgr +less 0x2c shift altgr +guillemotright 0x2d altgr +greater 0x2d shift altgr +cent 0x2e altgr +copyright 0x2e shift altgr +leftdoublequotemark 0x2f altgr +rightdoublequotemark 0x30 altgr +mu 0x32 altgr +masculine 0x32 shift altgr +comma 0x33 +less 0x33 shift +horizconnector 0x33 altgr +multiply 0x33 shift altgr +period 0x34 +greater 0x34 shift +periodcentered 0x34 altgr +division 0x34 shift altgr +slash 0x35 +question 0x35 shift +dead_belowdot 0x35 altgr +dead_abovedot 0x35 shift altgr +backslash 0x56 +bar 0x56 shift diff --git a/tools/ioemu/keymaps/en-us b/tools/ioemu/keymaps/en-us new file mode 100644 index 0000000000..f5784bbb39 --- /dev/null +++ b/tools/ioemu/keymaps/en-us @@ -0,0 +1,35 @@ +# generated from XKB map us +include common +map 0x409 +exclam 0x02 shift +at 0x03 shift +numbersign 0x04 shift +dollar 0x05 shift +percent 0x06 shift +asciicircum 0x07 shift +ampersand 0x08 shift +asterisk 0x09 shift +parenleft 0x0a shift +parenright 0x0b shift +minus 0x0c +underscore 0x0c shift +equal 0x0d +plus 0x0d shift +bracketleft 0x1a +braceleft 0x1a shift +bracketright 0x1b +braceright 0x1b shift +semicolon 0x27 +colon 0x27 shift +apostrophe 0x28 +quotedbl 0x28 shift +grave 0x29 +asciitilde 0x29 shift +backslash 0x2b +bar 0x2b shift +comma 0x33 +less 0x33 shift +period 0x34 +greater 0x34 shift +slash 0x35 +question 0x35 shift diff --git a/tools/ioemu/keymaps/es b/tools/ioemu/keymaps/es new file mode 100644 index 0000000000..0c29eec5ad --- /dev/null +++ b/tools/ioemu/keymaps/es @@ -0,0 +1,105 @@ +# generated from XKB map es +include common +map 0x40a +exclam 0x02 shift +bar 0x02 altgr +quotedbl 0x03 shift +at 0x03 altgr +oneeighth 0x03 shift altgr +periodcentered 0x04 shift +numbersign 0x04 altgr +sterling 0x04 shift altgr +dollar 0x05 shift +asciitilde 0x05 altgr +percent 0x06 shift +onehalf 0x06 altgr +threeeighths 0x06 shift altgr +ampersand 0x07 shift +notsign 0x07 altgr +fiveeighths 0x07 shift altgr +slash 0x08 shift +seveneighths 0x08 shift altgr +parenleft 0x09 shift +trademark 0x09 shift altgr +parenright 0x0a shift +plusminus 0x0a shift altgr +equal 0x0b shift +degree 0x0b shift altgr +apostrophe 0x0c +question 0x0c shift +exclamdown 0x0d +questiondown 0x0d shift +Greek_OMEGA 0x10 shift altgr +lstroke 0x11 altgr +Lstroke 0x11 shift altgr +EuroSign 0x12 altgr +paragraph 0x13 altgr +registered 0x13 shift altgr +tslash 0x14 altgr +Tslash 0x14 shift altgr +leftarrow 0x15 altgr +yen 0x15 shift altgr +downarrow 0x16 altgr +uparrow 0x16 shift altgr +rightarrow 0x17 altgr +idotless 0x17 shift altgr +oslash 0x18 altgr +Ooblique 0x18 shift altgr +thorn 0x19 altgr +THORN 0x19 shift altgr +dead_grave 0x1a +dead_circumflex 0x1a shift +bracketleft 0x1a altgr +dead_abovering 0x1a shift altgr +plus 0x1b +asterisk 0x1b shift +bracketright 0x1b altgr +dead_macron 0x1b shift altgr +ae 0x1e altgr +AE 0x1e shift altgr +ssharp 0x1f altgr +section 0x1f shift altgr +eth 0x20 altgr +ETH 0x20 shift altgr +dstroke 0x21 altgr +eng 0x22 altgr +ENG 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +kra 0x25 altgr +lstroke 0x26 altgr +Lstroke 0x26 shift altgr +ntilde 0x27 +Ntilde 0x27 shift +dead_doubleacute 0x27 shift altgr +dead_acute 0x28 +dead_diaeresis 0x28 shift +braceleft 0x28 altgr +masculine 0x29 +ordfeminine 0x29 shift +backslash 0x29 altgr +ccedilla 0x2b +Ccedilla 0x2b shift +braceright 0x2b altgr +dead_breve 0x2b shift altgr +guillemotleft 0x2c altgr +less 0x56 +greater 0x56 shift +guillemotright 0x2d altgr +cent 0x2e altgr +copyright 0x2e shift altgr +leftdoublequotemark 0x2f altgr +grave 0x2f shift altgr +rightdoublequotemark 0x30 altgr +mu 0x32 altgr +comma 0x33 +semicolon 0x33 shift +horizconnector 0x33 altgr +multiply 0x33 shift altgr +period 0x34 +colon 0x34 shift +division 0x34 shift altgr +minus 0x35 +underscore 0x35 shift +dead_belowdot 0x35 altgr +dead_abovedot 0x35 shift altgr diff --git a/tools/ioemu/keymaps/et b/tools/ioemu/keymaps/et new file mode 100644 index 0000000000..b5a73fef70 --- /dev/null +++ b/tools/ioemu/keymaps/et @@ -0,0 +1,86 @@ +map 0x00000425 +include common + +# +# Top row +# +dead_caron 0x29 +dead_tilde 0x29 shift + +# 1 +exclam 0x2 shift + +# 2 +quotedbl 0x3 shift +at 0x3 altgr + +# 3 +numbersign 0x4 shift +sterling 0x4 altgr +# 4 +currency 0x5 shift +dollar 0x5 altgr +# 5 +percent 0x6 shift +# 6 +ampersand 0x7 shift +# 7 +slash 0x8 shift +braceleft 0x8 altgr +# 8 +parenleft 0x9 shift +bracketleft 0x9 altgr +# 9 +parenright 0xa shift +bracketright 0xa altgr +# 0 +equal 0xb shift +braceright 0xb altgr + +plus 0xc +question 0xc shift +backslash 0xc altgr + +acute 0xd +dead_acute 0xd +grave 0xd shift +dead_grave 0xd shift + +# +# QWERTY first row +# +EuroSign 0x12 altgr +udiaeresis 0x1a +Udiaeresis 0x1a shift +otilde 0x1b +Otilde 0x1b shift +section 0x1b altgr + +# +# QWERTY second row +# +scaron 0x1f altgr +Scaron 0x1f altgr shift +odiaeresis 0x27 +Odiaeresis 0x27 shift +adiaeresis 0x28 +Adiaeresis 0x28 shift +asciicircum 0x28 altgr +apostrophe 0x2b +asterisk 0x2b shift +onehalf 0x2b altgr +# +# QWERTY third row +# +less 0x56 +greater 0x56 shift +bar 0x56 altgr +zcaron 0x2c altgr +Zcaron 0x2c altgr shift +comma 0x33 +semicolon 0x33 shift +period 0x34 +colon 0x34 shift +minus 0x35 +underscore 0x35 shift + diff --git a/tools/ioemu/keymaps/fi b/tools/ioemu/keymaps/fi new file mode 100644 index 0000000000..2a4e0f0454 --- /dev/null +++ b/tools/ioemu/keymaps/fi @@ -0,0 +1,124 @@ +# generated from XKB map se_FI +include common +map 0x40b +exclam 0x02 shift +exclamdown 0x02 altgr +onesuperior 0x02 shift altgr +quotedbl 0x03 shift +at 0x03 altgr +twosuperior 0x03 shift altgr +numbersign 0x04 shift +sterling 0x04 altgr +threesuperior 0x04 shift altgr +currency 0x05 shift +dollar 0x05 altgr +onequarter 0x05 shift altgr +percent 0x06 shift +onehalf 0x06 altgr +cent 0x06 shift altgr +ampersand 0x07 shift +yen 0x07 altgr +fiveeighths 0x07 shift altgr +slash 0x08 shift +braceleft 0x08 altgr +division 0x08 shift altgr +parenleft 0x09 shift +bracketleft 0x09 altgr +guillemotleft 0x09 shift altgr +parenright 0x0a shift +bracketright 0x0a altgr +guillemotright 0x0a shift altgr +equal 0x0b shift +braceright 0x0b altgr +degree 0x0b shift altgr +plus 0x0c +question 0x0c shift +backslash 0x0c altgr +questiondown 0x0c shift altgr +dead_acute 0x0d +dead_grave 0x0d shift +plusminus 0x0d altgr +notsign 0x0d shift altgr +at 0x10 altgr +Greek_OMEGA 0x10 shift altgr +lstroke 0x11 altgr +Lstroke 0x11 shift altgr +EuroSign 0x12 altgr +cent 0x12 shift altgr +registered 0x13 altgr +thorn 0x14 altgr +THORN 0x14 shift altgr +leftarrow 0x15 altgr +yen 0x15 shift altgr +downarrow 0x16 altgr +uparrow 0x16 shift altgr +rightarrow 0x17 altgr +idotless 0x17 shift altgr +oe 0x18 altgr +OE 0x18 shift altgr +thorn 0x19 altgr +THORN 0x19 shift altgr +aring 0x1a +Aring 0x1a shift +dead_diaeresis 0x1a altgr +dead_abovering 0x1a shift altgr +dead_diaeresis 0x1b +dead_circumflex 0x1b shift +dead_tilde 0x1b altgr +dead_caron 0x1b shift altgr +ordfeminine 0x1e altgr +masculine 0x1e shift altgr +ssharp 0x1f altgr +section 0x1f shift altgr +eth 0x20 altgr +ETH 0x20 shift altgr +dstroke 0x21 altgr +ordfeminine 0x21 shift altgr +eng 0x22 altgr +ENG 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +kra 0x25 altgr +ampersand 0x25 shift altgr +lstroke 0x26 altgr +Lstroke 0x26 shift altgr +odiaeresis 0x27 +Odiaeresis 0x27 shift +oslash 0x27 altgr +Ooblique 0x27 shift altgr +adiaeresis 0x28 +Adiaeresis 0x28 shift +ae 0x28 altgr +AE 0x28 shift altgr +section 0x29 +onehalf 0x29 shift +paragraph 0x29 altgr +threequarters 0x29 shift altgr +apostrophe 0x2b +asterisk 0x2b shift +acute 0x2b altgr +multiply 0x2b shift altgr +guillemotleft 0x2c altgr +less 0x2c shift altgr +guillemotright 0x2d altgr +greater 0x2d shift altgr +copyright 0x2e altgr +leftdoublequotemark 0x2f altgr +grave 0x2f shift altgr +rightdoublequotemark 0x30 altgr +apostrophe 0x30 shift altgr +mu 0x32 altgr +masculine 0x32 shift altgr +comma 0x33 +semicolon 0x33 shift +dead_cedilla 0x33 altgr +dead_ogonek 0x33 shift altgr +period 0x34 +colon 0x34 shift +periodcentered 0x34 altgr +dead_abovedot 0x34 shift altgr +minus 0x35 +underscore 0x35 shift +hyphen 0x35 altgr +macron 0x35 shift altgr +nobreakspace 0x39 altgr diff --git a/tools/ioemu/keymaps/fo b/tools/ioemu/keymaps/fo new file mode 100644 index 0000000000..83add423c6 --- /dev/null +++ b/tools/ioemu/keymaps/fo @@ -0,0 +1,77 @@ +map 0x438 +include common + +# +# Top row +# +onehalf 0x29 +section 0x29 shift + +# 1 +exclam 0x2 shift + +# 2 +quotedbl 0x3 shift +at 0x3 altgr + +# 3 +numbersign 0x4 shift +sterling 0x4 altgr +# 4 +currency 0x5 shift +dollar 0x5 altgr +# 5 +percent 0x6 shift +# 6 +ampersand 0x7 shift +# 7 +slash 0x8 shift +braceleft 0x8 altgr +# 8 +parenleft 0x9 shift +bracketleft 0x9 altgr +# 9 +parenright 0xa shift +bracketright 0xa altgr +# 0 +equal 0xb shift +braceright 0xb altgr + +plus 0xc +question 0xc shift +plusminus 0xc altgr + +bar 0xd altgr +dead_acute 0xd + +# +# QWERTY first row +# +EuroSign 0x12 altgr +aring 0x1a +Aring 0x1a shift +eth 0x1b addupper +asciitilde 0x1b altgr + +# +# QWERTY second row +# +ae 0x27 addupper +oslash 0x28 +Ooblique 0x28 shift +apostrophe 0x2b +asterisk 0x2b shift + +# +# QWERTY third row +# +less 0x56 +greater 0x56 shift +backslash 0x56 altgr +comma 0x33 +semicolon 0x33 shift +period 0x34 +colon 0x34 shift +minus 0x35 +underscore 0x35 shift + diff --git a/tools/ioemu/keymaps/fr b/tools/ioemu/keymaps/fr new file mode 100644 index 0000000000..cbb45910f4 --- /dev/null +++ b/tools/ioemu/keymaps/fr @@ -0,0 +1,181 @@ +include common +map 0x40c +# +# Top row +# +twosuperior 0x29 +notsign 0x29 altgr + +ampersand 0x02 +1 0x02 shift +onesuperior 0x02 altgr +exclamdown 0x02 shift altgr + +eacute 0x03 +2 0x03 shift +asciitilde 0x03 altgr +oneeighth 0x03 shift altgr + +quotedbl 0x04 +3 0x04 shift +numbersign 0x04 altgr + +apostrophe 0x05 +4 0x05 shift +braceleft 0x05 altgr + +parenleft 0x06 +5 0x06 shift +bracketleft 0x06 altgr +threeeighths 0x06 shift altgr + +minus 0x07 +6 0x07 shift +bar 0x07 altgr +fiveeighths 0x07 shift altgr + +egrave 0x08 +7 0x08 shift +grave 0x08 altgr +seveneighths 0x08 shift altgr + +underscore 0x09 +8 0x09 shift +backslash 0x09 altgr +trademark 0x09 shift altgr + +ccedilla 0x0a +9 0x0a shift +asciicircum 0x0a altgr +plusminus 0x0a shift altgr + +agrave 0x0b +0 0x0b shift +at 0x0b altgr + +parenright 0x0c +degree 0x0c shift +bracketright 0x0c altgr +questiondown 0x0c shift altgr + +equal 0x0d +plus 0x0d shift +braceright 0x0d altgr +dead_ogonek 0x0d shift altgr + +# +# AZERTY first row +# + +a 0x10 addupper +ae 0x10 altgr +AE 0x10 shift altgr + +z 0x11 addupper +guillemotleft 0x11 altgr + +EuroSign 0x12 altgr + +paragraph 0x13 altgr +registered 0x13 shift altgr + +tslash 0x14 altgr +Tslash 0x14 shift altgr + +leftarrow 0x15 altgr +yen 0x15 shift altgr + +downarrow 0x16 altgr +uparrow 0x16 shift altgr + +rightarrow 0x17 altgr +idotless 0x17 shift altgr + +oslash 0x18 altgr +Ooblique 0x18 shift altgr + +thorn 0x19 altgr +THORN 0x19 shift altgr + +dead_circumflex 0x1a +dead_diaeresis 0x1a shift +dead_abovering 0x1a shift altgr + +dollar 0x1b +sterling 0x1b shift +currency 0x1b altgr +dead_macron 0x1b shift altgr + +# +# AZERTY second row +# +q 0x1e addupper +Greek_OMEGA 0x1e shift altgr + +ssharp 0x1f altgr + +eth 0x20 altgr +ETH 0x20 shift altgr + +dstroke 0x21 altgr +ordfeminine 0x21 shift altgr + +eng 0x22 altgr +ENG 0x22 shift altgr + +hstroke 0x23 altgr +Hstroke 0x23 shift altgr + +kra 0x25 altgr + +lstroke 0x26 altgr +Lstroke 0x26 shift altgr + +m 0x27 addupper +masculine 0x27 shift altgr + +ugrave 0x28 +percent 0x28 shift +dead_caron 0x28 shift altgr + +asterisk 0x2b +mu 0x2b shift +dead_grave 0x2b altgr +dead_breve 0x2b shift altgr + +# +# AZERTY third row +# +less 0x56 +greater 0x56 shift + +w 0x2c addupper + +guillemotright 0x2d altgr + +cent 0x2e altgr +copyright 0x2e shift altgr + +leftdoublequotemark 0x2f altgr + +rightdoublequotemark 0x30 altgr + +comma 0x32 +question 0x32 shift +dead_acute 0x32 altgr +dead_doubleacute 0x32 shift altgr + +semicolon 0x33 +period 0x33 shift +horizconnector 0x33 altgr +multiply 0x33 shift altgr + +colon 0x34 +slash 0x34 shift +periodcentered 0x34 altgr +division 0x34 shift altgr + +exclam 0x35 +section 0x35 shift +dead_belowdot 0x35 altgr +dead_abovedot 0x35 shift altgr diff --git a/tools/ioemu/keymaps/fr-be b/tools/ioemu/keymaps/fr-be new file mode 100644 index 0000000000..92d668eb61 --- /dev/null +++ b/tools/ioemu/keymaps/fr-be @@ -0,0 +1,140 @@ +# generated from XKB map be +include common +map 0x80c +ampersand 0x02 +1 0x02 shift +bar 0x02 altgr +exclamdown 0x02 shift altgr +eacute 0x03 +2 0x03 shift +at 0x03 altgr +oneeighth 0x03 shift altgr +quotedbl 0x04 +3 0x04 shift +numbersign 0x04 altgr +sterling 0x04 shift altgr +apostrophe 0x05 +4 0x05 shift +onequarter 0x05 altgr +dollar 0x05 shift altgr +parenleft 0x06 +5 0x06 shift +onehalf 0x06 altgr +threeeighths 0x06 shift altgr +section 0x07 +6 0x07 shift +asciicircum 0x07 altgr +fiveeighths 0x07 shift altgr +egrave 0x08 +7 0x08 shift +braceleft 0x08 altgr +seveneighths 0x08 shift altgr +exclam 0x09 +8 0x09 shift +bracketleft 0x09 altgr +trademark 0x09 shift altgr +ccedilla 0x0a +9 0x0a shift +braceleft 0x0a altgr +plusminus 0x0a shift altgr +agrave 0x0b +0 0x0b shift +braceright 0x0b altgr +degree 0x0b shift altgr +parenright 0x0c +degree 0x0c shift +backslash 0x0c altgr +questiondown 0x0c shift altgr +minus 0x0d +underscore 0x0d shift +dead_cedilla 0x0d altgr +dead_ogonek 0x0d shift altgr +a 0x10 addupper +at 0x10 altgr +Greek_OMEGA 0x10 shift altgr +z 0x11 addupper +lstroke 0x11 altgr +Lstroke 0x11 shift altgr +EuroSign 0x12 altgr +cent 0x12 shift altgr +paragraph 0x13 altgr +registered 0x13 shift altgr +tslash 0x14 altgr +Tslash 0x14 shift altgr +leftarrow 0x15 altgr +yen 0x15 shift altgr +downarrow 0x16 altgr +uparrow 0x16 shift altgr +rightarrow 0x17 altgr +idotless 0x17 shift altgr +oslash 0x18 altgr +Ooblique 0x18 shift altgr +thorn 0x19 altgr +THORN 0x19 shift altgr +dead_circumflex 0x1a +dead_diaeresis 0x1a shift +bracketleft 0x1a altgr +dead_abovering 0x1a shift altgr +dollar 0x1b +asterisk 0x1b shift +bracketright 0x1b altgr +dead_macron 0x1b shift altgr +q 0x1e addupper +ae 0x1e altgr +AE 0x1e shift altgr +ssharp 0x1f altgr +section 0x1f shift altgr +eth 0x20 altgr +ETH 0x20 shift altgr +dstroke 0x21 altgr +ordfeminine 0x21 shift altgr +eng 0x22 altgr +ENG 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +kra 0x25 altgr +ampersand 0x25 shift altgr +lstroke 0x26 altgr +Lstroke 0x26 shift altgr +m 0x27 addupper +dead_acute 0x27 altgr +dead_doubleacute 0x27 shift altgr +ugrave 0x28 +percent 0x28 shift +dead_acute 0x28 altgr +dead_caron 0x28 shift altgr +twosuperior 0x29 +threesuperior 0x29 shift +notsign 0x29 altgr +mu 0x2b +sterling 0x2b shift +dead_grave 0x2b altgr +dead_breve 0x2b shift altgr +w 0x2c addupper +guillemotleft 0x2c altgr +less 0x2c shift altgr +guillemotright 0x2d altgr +greater 0x2d shift altgr +cent 0x2e altgr +copyright 0x2e shift altgr +leftdoublequotemark 0x2f altgr +grave 0x2f shift altgr +rightdoublequotemark 0x30 altgr +apostrophe 0x30 shift altgr +comma 0x32 +question 0x32 shift +dead_cedilla 0x32 altgr +masculine 0x32 shift altgr +semicolon 0x33 +period 0x33 shift +horizconnector 0x33 altgr +multiply 0x33 shift altgr +colon 0x34 +slash 0x34 shift +periodcentered 0x34 altgr +division 0x34 shift altgr +equal 0x35 +plus 0x35 shift +dead_tilde 0x35 altgr +dead_abovedot 0x35 shift altgr +backslash 0x56 altgr diff --git a/tools/ioemu/keymaps/fr-ca b/tools/ioemu/keymaps/fr-ca new file mode 100644 index 0000000000..b645208e42 --- /dev/null +++ b/tools/ioemu/keymaps/fr-ca @@ -0,0 +1,50 @@ +# Canadian French +# By Simon Germain +include common +map 0xc0c + +backslash 0x29 altgr +plusminus 0x2 altgr +at 0x3 altgr +sterling 0x4 altgr +cent 0x5 altgr +currency 0x6 altgr +notsign 0x7 altgr +bar 0x29 shift +twosuperior 0x9 altgr +threesuperior 0xa altgr +onequarter 0xb altgr +onehalf 0xc altgr +threequarters 0xd altgr +section 0x18 altgr +paragraph 0x19 altgr +bracketleft 0x1a altgr +bracketright 0x1b altgr +asciitilde 0x27 altgr +braceleft 0x28 altgr +braceright 0x2b altgr +less 0x2b +greater 0x2b shift +guillemotleft 0x56 +guillemotright 0x56 shift +degree 0x56 altgr +mu 0x32 altgr +eacute 0x35 +dead_acute 0x35 altgr +dead_grave 0x28 +dead_circumflex 0x1a +dead_circumflex 0x1a shift +dead_cedilla 0x1b +dead_diaeresis 0x1b shift +exclam 0x2 shift +quotedbl 0x3 shift +slash 0x4 shift +dollar 0x5 shift +percent 0x6 shift +question 0x7 shift +ampersand 0x8 shift +asterisk 0x9 shift +parenleft 0xa shift +parenright 0xb shift +underscore 0xc shift +plus 0xd shift diff --git a/tools/ioemu/keymaps/fr-ch b/tools/ioemu/keymaps/fr-ch new file mode 100644 index 0000000000..4620d2033b --- /dev/null +++ b/tools/ioemu/keymaps/fr-ch @@ -0,0 +1,114 @@ +# generated from XKB map fr_CH +include common +map 0x100c +exclam 0x02 shift +onesuperior 0x02 altgr +exclamdown 0x02 shift altgr +quotedbl 0x03 shift +twosuperior 0x03 altgr +oneeighth 0x03 shift altgr +section 0x04 shift +threesuperior 0x04 altgr +sterling 0x04 shift altgr +dollar 0x05 shift +onequarter 0x05 altgr +currency 0x05 shift altgr +percent 0x06 shift +onehalf 0x06 altgr +threeeighths 0x06 shift altgr +ampersand 0x07 shift +threequarters 0x07 altgr +fiveeighths 0x07 shift altgr +slash 0x08 shift +braceleft 0x08 altgr +seveneighths 0x08 shift altgr +parenleft 0x09 shift +bracketleft 0x09 altgr +trademark 0x09 shift altgr +parenright 0x0a shift +bracketright 0x0a altgr +plusminus 0x0a shift altgr +equal 0x0b shift +braceright 0x0b altgr +ssharp 0x0c +question 0x0c shift +backslash 0x0c altgr +questiondown 0x0c shift altgr +acute 0x0d +dead_acute 0x0d +grave 0x0d shift +dead_grave 0x0d shift +dead_cedilla 0x0d altgr +dead_ogonek 0x0d shift altgr +at 0x10 altgr +Greek_OMEGA 0x10 shift altgr +EuroSign 0x12 altgr +paragraph 0x13 altgr +registered 0x13 shift altgr +tslash 0x14 altgr +Tslash 0x14 shift altgr +z 0x15 addupper +leftarrow 0x15 altgr +yen 0x15 shift altgr +downarrow 0x16 altgr +uparrow 0x16 shift altgr +rightarrow 0x17 altgr +idotless 0x17 shift altgr +oslash 0x18 altgr +Ooblique 0x18 shift altgr +thorn 0x19 altgr +THORN 0x19 shift altgr +udiaeresis 0x1a +Udiaeresis 0x1a shift +dead_diaeresis 0x1a altgr +dead_abovering 0x1a shift altgr +plus 0x1b +asterisk 0x1b shift +asciitilde 0x1b altgr +dead_tilde 0x1b altgr +dead_macron 0x1b shift altgr +ae 0x1e altgr +AE 0x1e shift altgr +eth 0x20 altgr +ETH 0x20 shift altgr +dstroke 0x21 altgr +ordfeminine 0x21 shift altgr +eng 0x22 altgr +ENG 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +kra 0x25 altgr +odiaeresis 0x27 +Odiaeresis 0x27 shift +dead_doubleacute 0x27 altgr +adiaeresis 0x28 +Adiaeresis 0x28 shift +dead_caron 0x28 shift altgr +asciicircum 0x29 +dead_circumflex 0x29 +degree 0x29 shift +notsign 0x29 altgr +numbersign 0x2b +apostrophe 0x2b shift +dead_breve 0x2b shift altgr +y 0x2c addupper +guillemotleft 0x2c altgr +guillemotright 0x2d altgr +cent 0x2e altgr +copyright 0x2e shift altgr +leftdoublequotemark 0x2f altgr +rightdoublequotemark 0x30 altgr +mu 0x32 altgr +masculine 0x32 shift altgr +comma 0x33 +semicolon 0x33 shift +horizconnector 0x33 altgr +multiply 0x33 shift altgr +period 0x34 +colon 0x34 shift +periodcentered 0x34 altgr +division 0x34 shift altgr +minus 0x35 +underscore 0x35 shift +dead_belowdot 0x35 altgr +dead_abovedot 0x35 shift altgr diff --git a/tools/ioemu/keymaps/hr b/tools/ioemu/keymaps/hr new file mode 100644 index 0000000000..613aa6925d --- /dev/null +++ b/tools/ioemu/keymaps/hr @@ -0,0 +1,125 @@ +# generated from XKB map hr +include common +map 0x41a +exclam 0x02 shift +asciitilde 0x02 altgr +dead_tilde 0x02 shift altgr +quotedbl 0x03 shift +dead_caron 0x03 altgr +caron 0x03 shift altgr +numbersign 0x04 shift +asciicircum 0x04 altgr +dead_circumflex 0x04 shift altgr +dollar 0x05 shift +dead_breve 0x05 altgr +breve 0x05 shift altgr +percent 0x06 shift +degree 0x06 altgr +dead_abovering 0x06 shift altgr +ampersand 0x07 shift +dead_ogonek 0x07 altgr +ogonek 0x07 shift altgr +slash 0x08 shift +grave 0x08 altgr +dead_grave 0x08 shift altgr +parenleft 0x09 shift +dead_abovedot 0x09 altgr +abovedot 0x09 shift altgr +parenright 0x0a shift +dead_acute 0x0a altgr +apostrophe 0x0a shift altgr +equal 0x0b shift +dead_doubleacute 0x0b altgr +doubleacute 0x0b shift altgr +apostrophe 0x0c +question 0x0c shift +dead_diaeresis 0x0c altgr +diaeresis 0x0c shift altgr +plus 0x0d +asterisk 0x0d shift +dead_cedilla 0x0d altgr +cedilla 0x0d shift altgr +backslash 0x10 altgr +Greek_OMEGA 0x10 shift altgr +bar 0x11 altgr +Lstroke 0x11 shift altgr +EuroSign 0x12 altgr +paragraph 0x13 altgr +registered 0x13 shift altgr +tslash 0x14 altgr +Tslash 0x14 shift altgr +z 0x15 addupper +leftarrow 0x15 altgr +yen 0x15 shift altgr +downarrow 0x16 altgr +uparrow 0x16 shift altgr +rightarrow 0x17 altgr +idotless 0x17 shift altgr +oslash 0x18 altgr +Ooblique 0x18 shift altgr +thorn 0x19 altgr +THORN 0x19 shift altgr +scaron 0x1a +Scaron 0x1a shift +division 0x1a altgr +dead_abovering 0x1a shift altgr +dstroke 0x1b +Dstroke 0x1b shift +multiply 0x1b altgr +dead_macron 0x1b shift altgr +ae 0x1e altgr +AE 0x1e shift altgr +ssharp 0x1f altgr +section 0x1f shift altgr +eth 0x20 altgr +ETH 0x20 shift altgr +bracketleft 0x21 altgr +ordfeminine 0x21 shift altgr +bracketright 0x22 altgr +ENG 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +lstroke 0x25 altgr +ampersand 0x25 shift altgr +Lstroke 0x26 altgr +ccaron 0x27 +Ccaron 0x27 shift +dead_acute 0x27 altgr +dead_doubleacute 0x27 shift altgr +cacute 0x28 +Cacute 0x28 shift +ssharp 0x28 altgr +dead_caron 0x28 shift altgr +dead_cedilla 0x29 +dead_diaeresis 0x29 shift +notsign 0x29 altgr +zcaron 0x2b +Zcaron 0x2b shift +currency 0x2b altgr +dead_breve 0x2b shift altgr +y 0x2c addupper +guillemotleft 0x2c altgr +less 0x2c shift altgr +guillemotright 0x2d altgr +greater 0x2d shift altgr +cent 0x2e altgr +copyright 0x2e shift altgr +at 0x2f altgr +grave 0x2f shift altgr +braceleft 0x30 altgr +apostrophe 0x30 shift altgr +braceright 0x31 altgr +section 0x32 altgr +masculine 0x32 shift altgr +comma 0x33 +semicolon 0x33 shift +horizconnector 0x33 altgr +multiply 0x33 shift altgr +period 0x34 +colon 0x34 shift +periodcentered 0x34 altgr +division 0x34 shift altgr +minus 0x35 +underscore 0x35 shift +dead_belowdot 0x35 altgr +dead_abovedot 0x35 shift altgr diff --git a/tools/ioemu/keymaps/hu b/tools/ioemu/keymaps/hu new file mode 100644 index 0000000000..8aba444417 --- /dev/null +++ b/tools/ioemu/keymaps/hu @@ -0,0 +1,115 @@ +# Hungarian keyboard layout (QWERTZ) +# Created by: The NeverGone + +include common +map 0x40e + + +# AltGr keys: +notsign 0x29 altgr +asciitilde 0x02 altgr +caron 0x03 altgr +asciicircum 0x04 altgr +breve 0x05 altgr +degree 0x06 altgr +ogonek 0x07 altgr +grave 0x08 altgr +abovedot 0x09 altgr +acute 0x0a altgr +doubleacute 0x0b altgr +diaeresis 0x0c altgr +cedilla 0x0d altgr +backslash 0x10 altgr +bar 0x11 altgr +EuroSign 0x12 altgr +Iacute 0x17 altgr +division 0x1a altgr +multiply 0x1b altgr +dstroke 0x1f altgr +Dstroke 0x20 altgr +bracketleft 0x21 altgr +bracketright 0x22 altgr +iacute 0x24 altgr +lstroke 0x25 altgr +Lstroke 0x26 altgr +dollar 0x27 altgr +ssharp 0x28 altgr +currency 0x2b altgr +less 0x56 altgr +greater 0x2c altgr +numbersign 0x2d altgr +ampersand 0x2e altgr +at 0x2f altgr +braceleft 0x30 altgr +braceright 0x31 altgr +semicolon 0x33 altgr +asterisk 0x35 altgr + + +# Shift keys: +section 0x29 shift +apostrophe 0x02 shift +quotedbl 0x03 shift +plus 0x04 shift +exclam 0x05 shift +percent 0x06 shift +slash 0x07 shift +equal 0x08 shift +parenleft 0x09 shift +parenright 0x0a shift +Odiaeresis 0x0b shift +Udiaeresis 0x0c shift +Oacute 0x0d shift +Z 0x15 shift +Odoubleacute 0x1a shift +Uacute 0x1b shift +Eacute 0x27 shift +Aacute 0x28 shift +Udoubleacute 0x2b shift +Y 0x2c shift +question 0x33 shift +colon 0x34 shift +underscore 0x35 shift +F13 0x3b shift +F14 0x3c shift +F15 0x3d shift +F16 0x3e shift +F17 0x3f shift +F18 0x40 shift +F19 0x41 shift +F20 0x42 shift +F21 0x43 shift +F22 0x44 shift +F23 0x57 shift +F24 0x58 shift + + +# Ctrl keys: +F25 0x3b ctrl +F26 0x3c ctrl +F27 0x3d ctrl +F28 0x3e ctrl +F29 0x3f ctrl +F30 0x40 ctrl +F31 0x41 ctrl +F32 0x42 ctrl +F33 0x43 ctrl +F34 0x44 ctrl +F35 0x57 ctrl +#NoSymbol 0x58 ctrl + + +0 0x29 +odiaeresis 0x0b +udiaeresis 0x0c +oacute 0x0d +z 0x15 +odoubleacute 0x1a +uacute 0x1b +eacute 0x27 +aacute 0x28 +udoubleacute 0x2b +y 0x2c +comma 0x33 +period 0x34 +minus 0x35 diff --git a/tools/ioemu/keymaps/is b/tools/ioemu/keymaps/is new file mode 100644 index 0000000000..8fde40f19a --- /dev/null +++ b/tools/ioemu/keymaps/is @@ -0,0 +1,140 @@ +# 2004-03-16 Halldór Guðmundsson and Morten Lange +# Keyboard definition file for the Icelandic keyboard +# to be used in rdesktop 1.3.x ( See rdesktop.org) +# generated from XKB map de, and changed manually +# Location for example /usr/local/share/rdesktop/keymaps/is +include common +map 0x40f +exclam 0x02 shift +onesuperior 0x02 altgr +exclamdown 0x02 shift altgr +quotedbl 0x03 shift +twosuperior 0x03 altgr +oneeighth 0x03 shift altgr +#section 0x04 shift +numbersign 0x04 shift +threesuperior 0x04 altgr +sterling 0x04 shift altgr +dollar 0x05 shift +onequarter 0x05 altgr +currency 0x05 shift altgr +percent 0x06 shift +onehalf 0x06 altgr +threeeighths 0x06 shift altgr +ampersand 0x07 shift +threequarters 0x07 altgr +fiveeighths 0x07 shift altgr +slash 0x08 shift +braceleft 0x08 altgr +seveneighths 0x08 shift altgr +parenleft 0x09 shift +bracketleft 0x09 altgr +trademark 0x09 shift altgr +parenright 0x0a shift +bracketright 0x0a altgr +plusminus 0x0a shift altgr +equal 0x0b shift +braceright 0x0b altgr +#ssharp 0x0c +odiaeresis 0x0c +#question 0x0c shift +Odiaeresis 0x0c shift +backslash 0x0c altgr +questiondown 0x0c shift altgr +#acute 0x0d +minus 0x0d +#dead_acute 0x0d +#grave 0x0d shift +#dead_grave 0x0d shift +underscore 0x0d shift +dead_cedilla 0x0d altgr +dead_ogonek 0x0d shift altgr +at 0x10 altgr +Greek_OMEGA 0x10 shift altgr +EuroSign 0x12 altgr +paragraph 0x13 altgr +registered 0x13 shift altgr +tslash 0x14 altgr +Tslash 0x14 shift altgr +#z 0x15 addupper +leftarrow 0x15 altgr +yen 0x15 shift altgr +downarrow 0x16 altgr +uparrow 0x16 shift altgr +rightarrow 0x17 altgr +idotless 0x17 shift altgr +oslash 0x18 altgr +Ooblique 0x18 shift altgr +#thorn 0x19 altgr +#THORN 0x19 shift altgr +#udiaeresis 0x1a +#Udiaeresis 0x1a shift +#dead_diaeresis 0x1a altgr +#dead_abovering 0x1a shift altgr +eth 0x1a +ETH 0x1a shift +apostrophe 0x1b +question 0x1b shift +#plus 0x1b +#asterisk 0x1b shift +asciitilde 0x1b altgr +#grave 0x1b altgr +#dead_tilde 0x1b altgr +#dead_macron 0x1b shift altgr +#ae 0x1e altgr +#AE 0x1e shift altgr +#eth 0x20 altgr +#eth 0x20 +#ETH 0x20 shift altgr +#ETH 0x20 shift +dstroke 0x21 altgr +ordfeminine 0x21 shift altgr +eng 0x22 altgr +ENG 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +kra 0x25 altgr +#adiaeresis 0x27 +#Adiaeresis 0x27 shift +ae 0x27 +AE 0x27 shift +dead_doubleacute 0x27 altgr +#adiaeresis 0x28 +#Adiaeresis 0x28 shift +#dead_caron 0x28 shift altgr +#asciicircum 0x29 +acute 0x28 +dead_acute 0x28 +#dead_circumflex 0x29 +#degree 0x29 shift +#notsign 0x29 altgr +plus 0x2b +asterisk 0x2b shift +grave 0x2b altgr +#numbersign 0x2b +#apostrophe 0x2b shift +#dead_breve 0x2b shift altgr +#y 0x2c addupper +guillemotleft 0x2c altgr +guillemotright 0x2d altgr +cent 0x2e altgr +copyright 0x2e shift altgr +leftdoublequotemark 0x2f altgr +rightdoublequotemark 0x30 altgr +mu 0x32 altgr +masculine 0x32 shift altgr +comma 0x33 +semicolon 0x33 shift +horizconnector 0x33 altgr +multiply 0x33 shift altgr +period 0x34 +colon 0x34 shift +periodcentered 0x34 altgr +division 0x34 shift altgr +#minus 0x35 +#underscore 0x35 shift +thorn 0x35 +THORN 0x35 shift +dead_belowdot 0x35 altgr +dead_abovedot 0x35 shift altgr + diff --git a/tools/ioemu/keymaps/it b/tools/ioemu/keymaps/it new file mode 100644 index 0000000000..00ca73a3e2 --- /dev/null +++ b/tools/ioemu/keymaps/it @@ -0,0 +1,115 @@ +# generated from XKB map it +include common +map 0x410 +exclam 0x02 shift +onesuperior 0x02 altgr +exclamdown 0x02 shift altgr +quotedbl 0x03 shift +twosuperior 0x03 altgr +oneeighth 0x03 shift altgr +sterling 0x04 shift +threesuperior 0x04 altgr +dollar 0x05 shift +onequarter 0x05 altgr +percent 0x06 shift +onehalf 0x06 altgr +threeeighths 0x06 shift altgr +ampersand 0x07 shift +threequarters 0x07 altgr +fiveeighths 0x07 shift altgr +slash 0x08 shift +braceleft 0x08 altgr +seveneighths 0x08 shift altgr +parenleft 0x09 shift +trademark 0x09 shift altgr +parenright 0x0a shift +plusminus 0x0a shift altgr +equal 0x0b shift +braceright 0x0b altgr +degree 0x0b shift altgr +apostrophe 0x0c +question 0x0c shift +grave 0x0c altgr +questiondown 0x0c shift altgr +igrave 0x0d +asciicircum 0x0d shift +asciitilde 0x0d altgr +dead_ogonek 0x0d shift altgr +at 0x10 altgr +Greek_OMEGA 0x10 shift altgr +lstroke 0x11 altgr +Lstroke 0x11 shift altgr +EuroSign 0x12 altgr +cent 0x12 shift altgr +paragraph 0x13 altgr +registered 0x13 shift altgr +tslash 0x14 altgr +Tslash 0x14 shift altgr +leftarrow 0x15 altgr +yen 0x15 shift altgr +downarrow 0x16 altgr +uparrow 0x16 shift altgr +rightarrow 0x17 altgr +idotless 0x17 shift altgr +oslash 0x18 altgr +Ooblique 0x18 shift altgr +thorn 0x19 altgr +THORN 0x19 shift altgr +egrave 0x1a +eacute 0x1a shift +bracketleft 0x1a altgr +dead_abovering 0x1a shift altgr +plus 0x1b +asterisk 0x1b shift +bracketright 0x1b altgr +dead_macron 0x1b shift altgr +ae 0x1e altgr +AE 0x1e shift altgr +ssharp 0x1f altgr +section 0x1f shift altgr +eth 0x20 altgr +ETH 0x20 shift altgr +dstroke 0x21 altgr +ordfeminine 0x21 shift altgr +eng 0x22 altgr +ENG 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +kra 0x25 altgr +lstroke 0x26 altgr +Lstroke 0x26 shift altgr +ograve 0x27 +ccedilla 0x27 shift +at 0x27 altgr +dead_doubleacute 0x27 shift altgr +agrave 0x28 +degree 0x28 shift +numbersign 0x28 altgr +backslash 0x29 +bar 0x29 shift +notsign 0x29 altgr +ugrave 0x2b +section 0x2b shift +dead_grave 0x2b altgr +dead_breve 0x2b shift altgr +guillemotleft 0x2c altgr +guillemotright 0x2d altgr +cent 0x2e altgr +copyright 0x2e shift altgr +leftdoublequotemark 0x2f altgr +grave 0x2f shift altgr +rightdoublequotemark 0x30 altgr +mu 0x32 altgr +masculine 0x32 shift altgr +comma 0x33 +semicolon 0x33 shift +horizconnector 0x33 altgr +multiply 0x33 shift altgr +period 0x34 +colon 0x34 shift +periodcentered 0x34 altgr +division 0x34 shift altgr +minus 0x35 +underscore 0x35 shift +dead_belowdot 0x35 altgr +dead_abovedot 0x35 shift altgr diff --git a/tools/ioemu/keymaps/ja b/tools/ioemu/keymaps/ja new file mode 100644 index 0000000000..8fd0b9ef1b --- /dev/null +++ b/tools/ioemu/keymaps/ja @@ -0,0 +1,104 @@ +# generated from XKB map jp106 +include common +map 0x411 +exclam 0x02 shift +kana_NU 0x02 altgr +quotedbl 0x03 shift +kana_FU 0x03 altgr +numbersign 0x04 shift +kana_A 0x04 altgr +kana_a 0x04 shift altgr +dollar 0x05 shift +kana_U 0x05 altgr +kana_u 0x05 shift altgr +percent 0x06 shift +kana_E 0x06 altgr +kana_e 0x06 shift altgr +ampersand 0x07 shift +kana_O 0x07 altgr +kana_o 0x07 shift altgr +apostrophe 0x08 shift +kana_YA 0x08 altgr +kana_ya 0x08 shift altgr +parenleft 0x09 shift +kana_YU 0x09 altgr +kana_yu 0x09 shift altgr +parenright 0x0a shift +kana_YO 0x0a altgr +kana_yo 0x0a shift altgr +asciitilde 0x0b shift +kana_WA 0x0b altgr +kana_WO 0x0b shift altgr +minus 0x0c +equal 0x0c shift +kana_HO 0x0c altgr +asciicircum 0x0d +asciitilde 0x0d shift +kana_HE 0x0d altgr +kana_TA 0x10 altgr +kana_TE 0x11 altgr +kana_I 0x12 altgr +kana_i 0x12 shift altgr +kana_SU 0x13 altgr +kana_KA 0x14 altgr +kana_N 0x15 altgr +kana_NA 0x16 altgr +kana_NI 0x17 altgr +kana_RA 0x18 altgr +kana_SE 0x19 altgr +at 0x1a +grave 0x1a shift +voicedsound 0x1a altgr +bracketleft 0x1b +braceleft 0x1b shift +semivoicedsound 0x1b altgr +kana_openingbracket 0x1b shift altgr +kana_CHI 0x1e altgr +kana_TO 0x1f altgr +kana_SHI 0x20 altgr +kana_HA 0x21 altgr +kana_KI 0x22 altgr +kana_KU 0x23 altgr +kana_MA 0x24 altgr +kana_NO 0x25 altgr +kana_RI 0x26 altgr +semicolon 0x27 +plus 0x27 shift +kana_RE 0x27 altgr +colon 0x28 +asterisk 0x28 shift +kana_KE 0x28 altgr +Zenkaku_Hankaku 0x29 +bracketright 0x2b +braceright 0x2b shift +kana_MU 0x2b altgr +kana_closingbracket 0x2b shift altgr +kana_TSU 0x2c altgr +kana_tsu 0x2c shift altgr +kana_SA 0x2d altgr +kana_SO 0x2e altgr +kana_HI 0x2f altgr +kana_KO 0x30 altgr +kana_MI 0x31 altgr +kana_MO 0x32 altgr +comma 0x33 +less 0x33 shift +kana_NE 0x33 altgr +kana_comma 0x33 shift altgr +period 0x34 +greater 0x34 shift +kana_RU 0x34 altgr +kana_fullstop 0x34 shift altgr +slash 0x35 +question 0x35 shift +kana_ME 0x35 altgr +kana_conjunctive 0x35 shift altgr +Eisu_toggle 0x3a shift +Execute 0x54 shift +Kanji 0x70 +backslash 0x73 +bar 0x7d shift +underscore 0x73 shift +Henkan_Mode 0x79 +Katakana 0x70 +Muhenkan 0x7b diff --git a/tools/ioemu/keymaps/lt b/tools/ioemu/keymaps/lt new file mode 100644 index 0000000000..3d9d619ea5 --- /dev/null +++ b/tools/ioemu/keymaps/lt @@ -0,0 +1,57 @@ +# generated from XKB map lt +include common +map 0x427 +exclam 0x02 shift +aogonek 0x02 altgr +Aogonek 0x02 shift altgr +at 0x03 shift +ccaron 0x03 altgr +Ccaron 0x03 shift altgr +numbersign 0x04 shift +eogonek 0x04 altgr +Eogonek 0x04 shift altgr +dollar 0x05 shift +eabovedot 0x05 altgr +Eabovedot 0x05 shift altgr +percent 0x06 shift +iogonek 0x06 altgr +Iogonek 0x06 shift altgr +asciicircum 0x07 shift +scaron 0x07 altgr +Scaron 0x07 shift altgr +ampersand 0x08 shift +uogonek 0x08 altgr +Uogonek 0x08 shift altgr +asterisk 0x09 shift +umacron 0x09 altgr +Umacron 0x09 shift altgr +parenleft 0x0a shift +doublelowquotemark 0x0a altgr +parenright 0x0b shift +leftdoublequotemark 0x0b altgr +minus 0x0c +underscore 0x0c shift +equal 0x0d +plus 0x0d shift +zcaron 0x0d altgr +Zcaron 0x0d shift altgr +bracketleft 0x1a +braceleft 0x1a shift +bracketright 0x1b +braceright 0x1b shift +semicolon 0x27 +colon 0x27 shift +apostrophe 0x28 +quotedbl 0x28 shift +grave 0x29 +asciitilde 0x29 shift +backslash 0x2b +bar 0x2b shift +comma 0x33 +less 0x33 shift +period 0x34 +greater 0x34 shift +slash 0x35 +question 0x35 shift +endash 0x56 +EuroSign 0x56 shift diff --git a/tools/ioemu/keymaps/lv b/tools/ioemu/keymaps/lv new file mode 100644 index 0000000000..1d91727912 --- /dev/null +++ b/tools/ioemu/keymaps/lv @@ -0,0 +1,128 @@ +# generated from XKB map lv +include common +map 0x426 +exclam 0x02 shift +onesuperior 0x02 altgr +exclamdown 0x02 shift altgr +at 0x03 shift +twosuperior 0x03 altgr +oneeighth 0x03 shift altgr +numbersign 0x04 shift +threesuperior 0x04 altgr +sterling 0x04 shift altgr +dollar 0x05 shift +EuroSign 0x05 altgr +cent 0x05 shift altgr +percent 0x06 shift +onehalf 0x06 altgr +threeeighths 0x06 shift altgr +asciicircum 0x07 shift +threequarters 0x07 altgr +fiveeighths 0x07 shift altgr +ampersand 0x08 shift +braceleft 0x08 altgr +seveneighths 0x08 shift altgr +asterisk 0x09 shift +bracketleft 0x09 altgr +trademark 0x09 shift altgr +parenleft 0x0a shift +bracketright 0x0a altgr +plusminus 0x0a shift altgr +parenright 0x0b shift +braceright 0x0b altgr +degree 0x0b shift altgr +minus 0x0c +underscore 0x0c shift +backslash 0x0c altgr +questiondown 0x0c shift altgr +equal 0x0d +plus 0x0d shift +dead_cedilla 0x0d altgr +dead_ogonek 0x0d shift altgr +at 0x10 altgr +Greek_OMEGA 0x10 shift altgr +lstroke 0x11 altgr +Lstroke 0x11 shift altgr +emacron 0x12 altgr +Emacron 0x12 shift altgr +rcedilla 0x13 altgr +Rcedilla 0x13 shift altgr +tslash 0x14 altgr +Tslash 0x14 shift altgr +leftarrow 0x15 altgr +yen 0x15 shift altgr +umacron 0x16 altgr +Umacron 0x16 shift altgr +imacron 0x17 altgr +Imacron 0x17 shift altgr +omacron 0x18 altgr +Omacron 0x18 shift altgr +thorn 0x19 altgr +THORN 0x19 shift altgr +bracketleft 0x1a +braceleft 0x1a shift +dead_diaeresis 0x1a altgr +dead_abovering 0x1a shift altgr +bracketright 0x1b +braceright 0x1b shift +dead_tilde 0x1b altgr +dead_macron 0x1b shift altgr +ISO_Next_Group 0x1c shift +amacron 0x1e altgr +Amacron 0x1e shift altgr +scaron 0x1f altgr +Scaron 0x1f shift altgr +eth 0x20 altgr +ETH 0x20 shift altgr +dstroke 0x21 altgr +ordfeminine 0x21 shift altgr +gcedilla 0x22 altgr +Gcedilla 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +kcedilla 0x25 altgr +Kcedilla 0x25 shift altgr +lcedilla 0x26 altgr +Lcedilla 0x26 shift altgr +semicolon 0x27 +colon 0x27 shift +dead_acute 0x27 altgr +dead_doubleacute 0x27 shift altgr +apostrophe 0x28 +quotedbl 0x28 shift +leftdoublequotemark 0x28 altgr +doublelowquotemark 0x28 shift altgr +grave 0x29 +asciitilde 0x29 shift +notsign 0x29 altgr +backslash 0x2b +bar 0x2b shift +dead_grave 0x2b altgr +dead_breve 0x2b shift altgr +zcaron 0x2c altgr +Zcaron 0x2c shift altgr +guillemotright 0x2d altgr +greater 0x2d shift altgr +ccaron 0x2e altgr +Ccaron 0x2e shift altgr +leftdoublequotemark 0x2f altgr +grave 0x2f shift altgr +rightdoublequotemark 0x30 altgr +apostrophe 0x30 shift altgr +ncedilla 0x31 altgr +Ncedilla 0x31 shift altgr +mu 0x32 altgr +masculine 0x32 shift altgr +comma 0x33 +less 0x33 shift +horizconnector 0x33 altgr +multiply 0x33 shift altgr +period 0x34 +greater 0x34 shift +periodcentered 0x34 altgr +division 0x34 shift altgr +slash 0x35 +question 0x35 shift +dead_belowdot 0x35 altgr +dead_abovedot 0x35 shift altgr +nobreakspace 0x39 altgr diff --git a/tools/ioemu/keymaps/mk b/tools/ioemu/keymaps/mk new file mode 100644 index 0000000000..18c1504842 --- /dev/null +++ b/tools/ioemu/keymaps/mk @@ -0,0 +1,101 @@ +# generated from XKB map mk +include common +map 0x42f +exclam 0x02 shift +at 0x03 shift +doublelowquotemark 0x03 shift altgr +numbersign 0x04 shift +leftdoublequotemark 0x04 shift altgr +dollar 0x05 shift +percent 0x06 shift +asciicircum 0x07 shift +ampersand 0x08 shift +asterisk 0x09 shift +parenleft 0x0a shift +parenright 0x0b shift +minus 0x0c +underscore 0x0c shift +equal 0x0d +plus 0x0d shift +Cyrillic_lje 0x10 altgr +Cyrillic_LJE 0x10 shift altgr +Cyrillic_nje 0x11 altgr +Cyrillic_NJE 0x11 shift altgr +Cyrillic_ie 0x12 altgr +Cyrillic_IE 0x12 shift altgr +Cyrillic_er 0x13 altgr +Cyrillic_ER 0x13 shift altgr +Cyrillic_te 0x14 altgr +Cyrillic_TE 0x14 shift altgr +Macedonia_dse 0x15 altgr +Macedonia_DSE 0x15 shift altgr +Cyrillic_u 0x16 altgr +Cyrillic_U 0x16 shift altgr +Cyrillic_i 0x17 altgr +Cyrillic_I 0x17 shift altgr +Cyrillic_o 0x18 altgr +Cyrillic_O 0x18 shift altgr +Cyrillic_pe 0x19 altgr +Cyrillic_PE 0x19 shift altgr +bracketleft 0x1a +braceleft 0x1a shift +Cyrillic_sha 0x1a altgr +Cyrillic_SHA 0x1a shift altgr +bracketright 0x1b +braceright 0x1b shift +Macedonia_gje 0x1b altgr +Macedonia_GJE 0x1b shift altgr +Cyrillic_a 0x1e altgr +Cyrillic_A 0x1e shift altgr +Cyrillic_es 0x1f altgr +Cyrillic_ES 0x1f shift altgr +Cyrillic_de 0x20 altgr +Cyrillic_DE 0x20 shift altgr +Cyrillic_ef 0x21 altgr +Cyrillic_EF 0x21 shift altgr +Cyrillic_ghe 0x22 altgr +Cyrillic_GHE 0x22 shift altgr +Cyrillic_ha 0x23 altgr +Cyrillic_HA 0x23 shift altgr +Cyrillic_je 0x24 altgr +Cyrillic_JE 0x24 shift altgr +Cyrillic_ka 0x25 altgr +Cyrillic_KA 0x25 shift altgr +Cyrillic_el 0x26 altgr +Cyrillic_EL 0x26 shift altgr +semicolon 0x27 +colon 0x27 shift +Cyrillic_che 0x27 altgr +Cyrillic_CHE 0x27 shift altgr +apostrophe 0x28 +quotedbl 0x28 shift +Macedonia_kje 0x28 altgr +Macedonia_KJE 0x28 shift altgr +grave 0x29 +asciitilde 0x29 shift +backslash 0x2b +bar 0x2b shift +Cyrillic_zhe 0x2b altgr +Cyrillic_ZHE 0x2b shift altgr +Cyrillic_ze 0x2c altgr +Cyrillic_ZE 0x2c shift altgr +Cyrillic_dzhe 0x2d altgr +Cyrillic_DZHE 0x2d shift altgr +Cyrillic_tse 0x2e altgr +Cyrillic_TSE 0x2e shift altgr +Cyrillic_ve 0x2f altgr +Cyrillic_VE 0x2f shift altgr +Cyrillic_be 0x30 altgr +Cyrillic_BE 0x30 shift altgr +Cyrillic_en 0x31 altgr +Cyrillic_EN 0x31 shift altgr +Cyrillic_em 0x32 altgr +Cyrillic_EM 0x32 shift altgr +comma 0x33 +less 0x33 shift +semicolon 0x33 shift altgr +period 0x34 +greater 0x34 shift +colon 0x34 shift altgr +slash 0x35 +question 0x35 shift diff --git a/tools/ioemu/keymaps/modifiers b/tools/ioemu/keymaps/modifiers new file mode 100644 index 0000000000..d8b019f040 --- /dev/null +++ b/tools/ioemu/keymaps/modifiers @@ -0,0 +1,17 @@ +Shift_R 0x36 +Shift_L 0x2a + +Alt_R 0xb8 +Mode_switch 0xb8 +Alt_L 0x38 + +Control_R 0x9d +Control_L 0x1d + +# Translate Super to Windows keys. +# This is hardcoded. See documentation for details. +Super_R 0xdb +Super_L 0xdc + +# Translate Menu to the Windows Application key. +Menu 0xdd diff --git a/tools/ioemu/keymaps/nl b/tools/ioemu/keymaps/nl new file mode 100644 index 0000000000..bc823bd2f7 --- /dev/null +++ b/tools/ioemu/keymaps/nl @@ -0,0 +1,60 @@ +# Dutch (Netherlands) +include common +map 0x413 + +exclam 0x02 shift +onesuperior 0x02 altgr +quotebl 0x03 shift +twosuperior 0x03 altgr +numbersign 0x04 shift +threesuperior 0x04 altgr +dollar 0x05 shift +onequarter 0x05 altgr +percent 0x06 shift +onehalf 0x06 altgr +ampersand 0x07 shift +threequarters 0x07 altgr +underscore 0x08 shift +sterling 0x08 altgr +parenleft 0x09 shift +braceleft 0x09 altgr +parenright 0x0a shift +braceright 0x0a altgr +apostrophe 0x0b shift +slash 0x0c +question 0x0c shift +backslash 0x0c altgr +degree 0x0d +dead_tilde 0x0d shift +dead_cedilla 0x0d altgr +EuroSign 0x12 altgr +paragraph 0x13 altgr +dead_diaeresis 0x1a +dead_circumflex 0x1a shift +asterisk 0x1b +bar 0x1b shift +ssharp 0x1f altgr +plus 0x27 +plusminus 0x27 shift +dead_acute 0x28 +dead_grave 0x28 shift +at 0x29 +section 0x29 shift +notsign 0x29 altgr +less 0x2b +greater 0x2b shift +guillemotleft 0x2c altgr +guillemotright 0x2d altgr +copyright 0x2e altgr +mu 0x32 altgr +comma 0x33 +semicolon 0x33 shift +period 0x34 +colon 0x34 shift +periodcentered 0x34 altgr +hyphen 0x35 +equal 0x35 shift +bracketright 0x56 +bracketleft 0x56 shift +brokenbar 0x56 altgr + diff --git a/tools/ioemu/keymaps/nl-be b/tools/ioemu/keymaps/nl-be new file mode 100644 index 0000000000..34fc881ad0 --- /dev/null +++ b/tools/ioemu/keymaps/nl-be @@ -0,0 +1,3 @@ +# Dutch (Belgium) +map 0x813 +include common diff --git a/tools/ioemu/keymaps/no b/tools/ioemu/keymaps/no new file mode 100644 index 0000000000..40a64790d1 --- /dev/null +++ b/tools/ioemu/keymaps/no @@ -0,0 +1,119 @@ +# generated from XKB map no +include common +map 0x414 +exclam 0x02 shift +exclamdown 0x02 altgr +onesuperior 0x02 shift altgr +quotedbl 0x03 shift +at 0x03 altgr +twosuperior 0x03 shift altgr +numbersign 0x04 shift +sterling 0x04 altgr +threesuperior 0x04 shift altgr +currency 0x05 shift +dollar 0x05 altgr +onequarter 0x05 shift altgr +percent 0x06 shift +onehalf 0x06 altgr +cent 0x06 shift altgr +ampersand 0x07 shift +yen 0x07 altgr +fiveeighths 0x07 shift altgr +slash 0x08 shift +braceleft 0x08 altgr +division 0x08 shift altgr +parenleft 0x09 shift +bracketleft 0x09 altgr +guillemotleft 0x09 shift altgr +parenright 0x0a shift +bracketright 0x0a altgr +guillemotright 0x0a shift altgr +equal 0x0b shift +braceright 0x0b altgr +degree 0x0b shift altgr +plus 0x0c +question 0x0c shift +plusminus 0x0c altgr +questiondown 0x0c shift altgr +backslash 0x0d +dead_grave 0x0d shift +dead_acute 0x0d altgr +notsign 0x0d shift altgr +Greek_OMEGA 0x10 shift altgr +lstroke 0x11 altgr +Lstroke 0x11 shift altgr +EuroSign 0x12 altgr +cent 0x12 shift altgr +registered 0x13 altgr +thorn 0x14 altgr +THORN 0x14 shift altgr +leftarrow 0x15 altgr +yen 0x15 shift altgr +downarrow 0x16 altgr +uparrow 0x16 shift altgr +rightarrow 0x17 altgr +idotless 0x17 shift altgr +oe 0x18 altgr +OE 0x18 shift altgr +thorn 0x19 altgr +THORN 0x19 shift altgr +aring 0x1a +Aring 0x1a shift +dead_diaeresis 0x1a altgr +dead_abovering 0x1a shift altgr +dead_diaeresis 0x1b +dead_circumflex 0x1b shift +asciicircum 0x01b shift +dead_tilde 0x1b altgr +asciitilde 0x1b altgr +dead_caron 0x1b shift altgr +ordfeminine 0x1e altgr +masculine 0x1e shift altgr +ssharp 0x1f altgr +section 0x1f shift altgr +eth 0x20 altgr +ETH 0x20 shift altgr +dstroke 0x21 altgr +ordfeminine 0x21 shift altgr +eng 0x22 altgr +ENG 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +kra 0x25 altgr +lstroke 0x26 altgr +Lstroke 0x26 shift altgr +oslash 0x27 +Ooblique 0x27 shift +dead_doubleacute 0x27 shift altgr +ae 0x28 +AE 0x28 shift +dead_caron 0x28 shift altgr +bar 0x29 +section 0x29 shift +brokenbar 0x29 altgr +paragraph 0x29 shift altgr +apostrophe 0x2b +asterisk 0x2b shift +multiply 0x2b shift altgr +guillemotleft 0x2c altgr +guillemotright 0x2d altgr +copyright 0x2e altgr +leftdoublequotemark 0x2f altgr +rightdoublequotemark 0x30 altgr +mu 0x32 altgr +masculine 0x32 shift altgr +comma 0x33 +semicolon 0x33 shift +dead_cedilla 0x33 altgr +dead_ogonek 0x33 shift altgr +period 0x34 +colon 0x34 shift +periodcentered 0x34 altgr +dead_abovedot 0x34 shift altgr +minus 0x35 +underscore 0x35 shift +hyphen 0x35 altgr +macron 0x35 shift altgr +nobreakspace 0x39 altgr +onehalf 0x56 altgr +threequarters 0x56 shift altgr diff --git a/tools/ioemu/keymaps/pl b/tools/ioemu/keymaps/pl new file mode 100644 index 0000000000..09c600d355 --- /dev/null +++ b/tools/ioemu/keymaps/pl @@ -0,0 +1,122 @@ +# generated from XKB map pl +include common +map 0x415 +exclam 0x02 shift +onesuperior 0x02 altgr +exclamdown 0x02 shift altgr +at 0x03 shift +twosuperior 0x03 altgr +oneeighth 0x03 shift altgr +numbersign 0x04 shift +threesuperior 0x04 altgr +sterling 0x04 shift altgr +dollar 0x05 shift +onequarter 0x05 altgr +percent 0x06 shift +onehalf 0x06 altgr +threeeighths 0x06 shift altgr +asciicircum 0x07 shift +threequarters 0x07 altgr +fiveeighths 0x07 shift altgr +ampersand 0x08 shift +braceleft 0x08 altgr +seveneighths 0x08 shift altgr +asterisk 0x09 shift +bracketleft 0x09 altgr +trademark 0x09 shift altgr +parenleft 0x0a shift +bracketright 0x0a altgr +plusminus 0x0a shift altgr +parenright 0x0b shift +braceright 0x0b altgr +degree 0x0b shift altgr +minus 0x0c +underscore 0x0c shift +backslash 0x0c altgr +questiondown 0x0c shift altgr +equal 0x0d +plus 0x0d shift +dead_cedilla 0x0d altgr +dead_ogonek 0x0d shift altgr +Greek_OMEGA 0x10 shift altgr +lstroke 0x11 altgr +Lstroke 0x11 shift altgr +eogonek 0x12 altgr +Eogonek 0x12 shift altgr +paragraph 0x13 altgr +registered 0x13 shift altgr +tslash 0x14 altgr +Tslash 0x14 shift altgr +leftarrow 0x15 altgr +yen 0x15 shift altgr +EuroSign 0x16 altgr +uparrow 0x16 shift altgr +rightarrow 0x17 altgr +idotless 0x17 shift altgr +oacute 0x18 altgr +Oacute 0x18 shift altgr +thorn 0x19 altgr +THORN 0x19 shift altgr +bracketleft 0x1a +braceleft 0x1a shift +dead_diaeresis 0x1a altgr +dead_abovering 0x1a shift altgr +bracketright 0x1b +braceright 0x1b shift +dead_tilde 0x1b altgr +dead_macron 0x1b shift altgr +aogonek 0x1e altgr +Aogonek 0x1e shift altgr +sacute 0x1f altgr +Sacute 0x1f shift altgr +eth 0x20 altgr +ETH 0x20 shift altgr +dstroke 0x21 altgr +ordfeminine 0x21 shift altgr +eng 0x22 altgr +ENG 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +kra 0x25 altgr +lstroke 0x26 altgr +Lstroke 0x26 shift altgr +semicolon 0x27 +colon 0x27 shift +dead_acute 0x27 altgr +dead_doubleacute 0x27 shift altgr +apostrophe 0x28 +quotedbl 0x28 shift +dead_circumflex 0x28 altgr +dead_caron 0x28 shift altgr +grave 0x29 +asciitilde 0x29 shift +notsign 0x29 altgr +backslash 0x2b +bar 0x2b shift +dead_grave 0x2b altgr +dead_breve 0x2b shift altgr +zabovedot 0x2c altgr +Zabovedot 0x2c shift altgr +zacute 0x2d altgr +Zacute 0x2d shift altgr +cacute 0x2e altgr +Cacute 0x2e shift altgr +leftdoublequotemark 0x2f altgr +grave 0x2f shift altgr +rightdoublequotemark 0x30 altgr +nacute 0x31 altgr +Nacute 0x31 shift altgr +mu 0x32 altgr +masculine 0x32 shift altgr +comma 0x33 +less 0x33 shift +horizconnector 0x33 altgr +multiply 0x33 shift altgr +period 0x34 +greater 0x34 shift +periodcentered 0x34 altgr +division 0x34 shift altgr +slash 0x35 +question 0x35 shift +dead_belowdot 0x35 altgr +dead_abovedot 0x35 shift altgr diff --git a/tools/ioemu/keymaps/pt b/tools/ioemu/keymaps/pt new file mode 100644 index 0000000000..c6941f651c --- /dev/null +++ b/tools/ioemu/keymaps/pt @@ -0,0 +1,113 @@ +# generated from XKB map pt +include common +map 0x816 +exclam 0x02 shift +onesuperior 0x02 altgr +exclamdown 0x02 shift altgr +quotedbl 0x03 shift +at 0x03 altgr +oneeighth 0x03 shift altgr +numbersign 0x04 shift +sterling 0x04 altgr +dollar 0x05 shift +section 0x05 altgr +percent 0x06 shift +onehalf 0x06 altgr +threeeighths 0x06 shift altgr +ampersand 0x07 shift +threequarters 0x07 altgr +fiveeighths 0x07 shift altgr +slash 0x08 shift +braceleft 0x08 altgr +seveneighths 0x08 shift altgr +parenleft 0x09 shift +bracketleft 0x09 altgr +trademark 0x09 shift altgr +parenright 0x0a shift +bracketright 0x0a altgr +plusminus 0x0a shift altgr +equal 0x0b shift +braceright 0x0b altgr +degree 0x0b shift altgr +apostrophe 0x0c +question 0x0c shift +backslash 0x0c altgr +questiondown 0x0c shift altgr +guillemotleft 0x0d +guillemotright 0x0d shift +dead_cedilla 0x0d altgr +dead_ogonek 0x0d shift altgr +Greek_OMEGA 0x10 shift altgr +lstroke 0x11 altgr +Lstroke 0x11 shift altgr +EuroSign 0x12 altgr +cent 0x12 shift altgr +paragraph 0x13 altgr +registered 0x13 shift altgr +tslash 0x14 altgr +Tslash 0x14 shift altgr +leftarrow 0x15 altgr +yen 0x15 shift altgr +downarrow 0x16 altgr +uparrow 0x16 shift altgr +rightarrow 0x17 altgr +idotless 0x17 shift altgr +oslash 0x18 altgr +Ooblique 0x18 shift altgr +thorn 0x19 altgr +THORN 0x19 shift altgr +plus 0x1a +asterisk 0x1a shift +dead_diaeresis 0x1a altgr +dead_abovering 0x1a shift altgr +dead_acute 0x1b +dead_grave 0x1b shift +dead_tilde 0x1b altgr +dead_macron 0x1b shift altgr +ae 0x1e altgr +AE 0x1e shift altgr +ssharp 0x1f altgr +eth 0x20 altgr +ETH 0x20 shift altgr +dstroke 0x21 altgr +ordfeminine 0x21 shift altgr +eng 0x22 altgr +ENG 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +kra 0x25 altgr +lstroke 0x26 altgr +Lstroke 0x26 shift altgr +ccedilla 0x27 +Ccedilla 0x27 shift +dead_doubleacute 0x27 shift altgr +masculine 0x28 +ordfeminine 0x28 shift +dead_circumflex 0x28 altgr +dead_caron 0x28 shift altgr +backslash 0x29 +bar 0x29 shift +notsign 0x29 altgr +dead_tilde 0x2b +dead_circumflex 0x2b shift +dead_breve 0x2b shift altgr +less 0x56 +greater 0x56 shift +cent 0x2e altgr +copyright 0x2e shift altgr +leftdoublequotemark 0x2f altgr +grave 0x2f shift altgr +rightdoublequotemark 0x30 altgr +mu 0x32 altgr +comma 0x33 +semicolon 0x33 shift +horizconnector 0x33 altgr +multiply 0x33 shift altgr +period 0x34 +colon 0x34 shift +periodcentered 0x34 altgr +division 0x34 shift altgr +minus 0x35 +underscore 0x35 shift +dead_belowdot 0x35 altgr +dead_abovedot 0x35 shift altgr diff --git a/tools/ioemu/keymaps/pt-br b/tools/ioemu/keymaps/pt-br new file mode 100644 index 0000000000..54bafc5dc3 --- /dev/null +++ b/tools/ioemu/keymaps/pt-br @@ -0,0 +1,69 @@ +# generated from XKB map br +include common +map 0x416 +exclam 0x02 shift +onesuperior 0x02 altgr +exclamdown 0x02 shift altgr +at 0x03 shift +twosuperior 0x03 altgr +onehalf 0x03 shift altgr +numbersign 0x04 shift +threesuperior 0x04 altgr +threequarters 0x04 shift altgr +dollar 0x05 shift +sterling 0x05 altgr +onequarter 0x05 shift altgr +percent 0x06 shift +cent 0x06 altgr +dead_diaeresis 0x07 shift +notsign 0x07 altgr +diaeresis 0x07 shift altgr +ampersand 0x08 shift +braceleft 0x08 altgr +asterisk 0x09 shift +bracketleft 0x09 altgr +parenleft 0x0a shift +bracketright 0x0a altgr +parenright 0x0b shift +braceright 0x0b altgr +minus 0x0c +underscore 0x0c shift +backslash 0x0c altgr +equal 0x0d +plus 0x0d shift +section 0x0d altgr +EuroSign 0x12 altgr +registered 0x13 altgr +dead_acute 0x1a +dead_grave 0x1a shift +acute 0x1a altgr +grave 0x1a shift altgr +bracketleft 0x1b +braceleft 0x1b shift +ordfeminine 0x1b altgr +ccedilla 0x27 +Ccedilla 0x27 shift +dead_tilde 0x28 +dead_circumflex 0x28 shift +asciitilde 0x28 altgr +asciicircum 0x28 shift altgr +apostrophe 0x29 +quotedbl 0x29 shift +bracketright 0x2b +braceright 0x2b shift +masculine 0x2b altgr +copyright 0x2e altgr +mu 0x32 altgr +comma 0x33 +less 0x33 shift +period 0x34 +greater 0x34 shift +semicolon 0x35 +colon 0x35 shift +comma 0x53 numlock +backslash 0x56 +bar 0x56 shift +slash 0x73 +question 0x73 shift +degree 0x73 altgr +KP_Decimal 0x34 diff --git a/tools/ioemu/keymaps/ru b/tools/ioemu/keymaps/ru new file mode 100644 index 0000000000..b3e7d24de5 --- /dev/null +++ b/tools/ioemu/keymaps/ru @@ -0,0 +1,109 @@ +# generated from XKB map ru +include common +map 0x419 +exclam 0x02 shift +at 0x03 shift +quotedbl 0x03 shift altgr +numbersign 0x04 shift +dollar 0x05 shift +asterisk 0x05 shift altgr +percent 0x06 shift +colon 0x06 shift altgr +asciicircum 0x07 shift +comma 0x07 shift altgr +ampersand 0x08 shift +period 0x08 shift altgr +asterisk 0x09 shift +semicolon 0x09 shift altgr +parenleft 0x0a shift +parenright 0x0b shift +minus 0x0c +underscore 0x0c shift +equal 0x0d +plus 0x0d shift +Cyrillic_shorti 0x10 altgr +Cyrillic_SHORTI 0x10 shift altgr +Cyrillic_tse 0x11 altgr +Cyrillic_TSE 0x11 shift altgr +Cyrillic_u 0x12 altgr +Cyrillic_U 0x12 shift altgr +Cyrillic_ka 0x13 altgr +Cyrillic_KA 0x13 shift altgr +Cyrillic_ie 0x14 altgr +Cyrillic_IE 0x14 shift altgr +Cyrillic_en 0x15 altgr +Cyrillic_EN 0x15 shift altgr +Cyrillic_ghe 0x16 altgr +Cyrillic_GHE 0x16 shift altgr +Cyrillic_sha 0x17 altgr +Cyrillic_SHA 0x17 shift altgr +Cyrillic_shcha 0x18 altgr +Cyrillic_SHCHA 0x18 shift altgr +Cyrillic_ze 0x19 altgr +Cyrillic_ZE 0x19 shift altgr +bracketleft 0x1a +braceleft 0x1a shift +Cyrillic_ha 0x1a altgr +Cyrillic_HA 0x1a shift altgr +bracketright 0x1b +braceright 0x1b shift +Cyrillic_hardsign 0x1b altgr +Cyrillic_HARDSIGN 0x1b shift altgr +Cyrillic_ef 0x1e altgr +Cyrillic_EF 0x1e shift altgr +Cyrillic_yeru 0x1f altgr +Cyrillic_YERU 0x1f shift altgr +Cyrillic_ve 0x20 altgr +Cyrillic_VE 0x20 shift altgr +Cyrillic_a 0x21 altgr +Cyrillic_A 0x21 shift altgr +Cyrillic_pe 0x22 altgr +Cyrillic_PE 0x22 shift altgr +Cyrillic_er 0x23 altgr +Cyrillic_ER 0x23 shift altgr +Cyrillic_o 0x24 altgr +Cyrillic_O 0x24 shift altgr +Cyrillic_el 0x25 altgr +Cyrillic_EL 0x25 shift altgr +Cyrillic_de 0x26 altgr +Cyrillic_DE 0x26 shift altgr +semicolon 0x27 +colon 0x27 shift +Cyrillic_zhe 0x27 altgr +Cyrillic_ZHE 0x27 shift altgr +apostrophe 0x28 +quotedbl 0x28 shift +Cyrillic_e 0x28 altgr +Cyrillic_E 0x28 shift altgr +grave 0x29 +asciitilde 0x29 shift +Cyrillic_io 0x29 altgr +Cyrillic_IO 0x29 shift altgr +backslash 0x2b +bar 0x2b shift +Cyrillic_ya 0x2c altgr +Cyrillic_YA 0x2c shift altgr +Cyrillic_che 0x2d altgr +Cyrillic_CHE 0x2d shift altgr +Cyrillic_es 0x2e altgr +Cyrillic_ES 0x2e shift altgr +Cyrillic_em 0x2f altgr +Cyrillic_EM 0x2f shift altgr +Cyrillic_i 0x30 altgr +Cyrillic_I 0x30 shift altgr +Cyrillic_te 0x31 altgr +Cyrillic_TE 0x31 shift altgr +Cyrillic_softsign 0x32 altgr +Cyrillic_SOFTSIGN 0x32 shift altgr +comma 0x33 +less 0x33 shift +Cyrillic_be 0x33 altgr +Cyrillic_BE 0x33 shift altgr +period 0x34 +greater 0x34 shift +Cyrillic_yu 0x34 altgr +Cyrillic_YU 0x34 shift altgr +slash 0x35 +question 0x35 shift +slash 0x56 altgr +bar 0x56 shift altgr diff --git a/tools/ioemu/keymaps/sl b/tools/ioemu/keymaps/sl new file mode 100644 index 0000000000..56835a92c3 --- /dev/null +++ b/tools/ioemu/keymaps/sl @@ -0,0 +1,110 @@ +# generated from XKB map sl +include common +map 0x424 +exclam 0x02 shift +asciitilde 0x02 altgr +dead_tilde 0x02 shift altgr +quotedbl 0x03 shift +dead_caron 0x03 altgr +caron 0x03 shift altgr +numbersign 0x04 shift +asciicircum 0x04 altgr +dead_circumflex 0x04 shift altgr +dollar 0x05 shift +dead_breve 0x05 altgr +breve 0x05 shift altgr +percent 0x06 shift +degree 0x06 altgr +dead_abovering 0x06 shift altgr +ampersand 0x07 shift +dead_ogonek 0x07 altgr +ogonek 0x07 shift altgr +slash 0x08 shift +grave 0x08 altgr +dead_grave 0x08 shift altgr +parenleft 0x09 shift +dead_abovedot 0x09 altgr +abovedot 0x09 shift altgr +parenright 0x0a shift +dead_acute 0x0a altgr +equal 0x0b shift +dead_doubleacute 0x0b altgr +doubleacute 0x0b shift altgr +apostrophe 0x0c +question 0x0c shift +dead_diaeresis 0x0c altgr +diaeresis 0x0c shift altgr +plus 0x0d +asterisk 0x0d shift +dead_cedilla 0x0d altgr +cedilla 0x0d shift altgr +backslash 0x10 altgr +Greek_OMEGA 0x10 shift altgr +bar 0x11 altgr +Lstroke 0x11 shift altgr +EuroSign 0x12 altgr +paragraph 0x13 altgr +registered 0x13 shift altgr +tslash 0x14 altgr +Tslash 0x14 shift altgr +z 0x15 addupper +leftarrow 0x15 altgr +yen 0x15 shift altgr +downarrow 0x16 altgr +uparrow 0x16 shift altgr +rightarrow 0x17 altgr +idotless 0x17 shift altgr +oslash 0x18 altgr +Ooblique 0x18 shift altgr +thorn 0x19 altgr +THORN 0x19 shift altgr +scaron 0x1a +Scaron 0x1a shift +division 0x1a altgr +dstroke 0x1b +Dstroke 0x1b shift +multiply 0x1b altgr +dead_macron 0x1b shift altgr +ae 0x1e altgr +AE 0x1e shift altgr +ssharp 0x1f altgr +section 0x1f shift altgr +eth 0x20 altgr +ETH 0x20 shift altgr +bracketleft 0x21 altgr +ordfeminine 0x21 shift altgr +bracketright 0x22 altgr +ENG 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +lstroke 0x25 altgr +Lstroke 0x26 altgr +ccaron 0x27 +Ccaron 0x27 shift +cacute 0x28 +Cacute 0x28 shift +ssharp 0x28 altgr +dead_cedilla 0x29 +notsign 0x29 altgr +zcaron 0x2b +Zcaron 0x2b shift +currency 0x2b altgr +y 0x2c addupper +guillemotleft 0x2c altgr +guillemotright 0x2d altgr +cent 0x2e altgr +copyright 0x2e shift altgr +at 0x2f altgr +braceleft 0x30 altgr +braceright 0x31 altgr +section 0x32 altgr +masculine 0x32 shift altgr +comma 0x33 +semicolon 0x33 shift +horizconnector 0x33 altgr +period 0x34 +colon 0x34 shift +periodcentered 0x34 altgr +minus 0x35 +underscore 0x35 shift +dead_belowdot 0x35 altgr diff --git a/tools/ioemu/keymaps/sv b/tools/ioemu/keymaps/sv new file mode 100644 index 0000000000..736d637b3f --- /dev/null +++ b/tools/ioemu/keymaps/sv @@ -0,0 +1,82 @@ +map 0x0000041d +include common + +# +# Top row +# +section 0x29 +onehalf 0x29 shift + +# 1 +exclam 0x2 shift + +# 2 +quotedbl 0x3 shift +at 0x3 altgr + +# 3 +numbersign 0x4 shift +sterling 0x4 altgr +# 4 +currency 0x5 shift +dollar 0x5 altgr +# 5 +percent 0x6 shift +# 6 +ampersand 0x7 shift +# 7 +slash 0x8 shift +braceleft 0x8 altgr +# 8 +parenleft 0x9 shift +bracketleft 0x9 altgr +# 9 +parenright 0xa shift +bracketright 0xa altgr +# 0 +equal 0xb shift +braceright 0xb altgr + +plus 0xc +question 0xc shift +backslash 0xc altgr + +acute 0xd +dead_acute 0xd +grave 0xd shift +dead_grave 0xd shift + +# +# QWERTY first row +# +EuroSign 0x12 altgr +aring 0x1a +Aring 0x1a shift +dead_diaeresis 0x1b +dead_circumflex 0x1b shift +dead_tilde 0x1b altgr + +# +# QWERTY second row +# +odiaeresis 0x27 +Odiaeresis 0x27 shift +adiaeresis 0x28 +Adiaeresis 0x28 shift +apostrophe 0x2b +asterisk 0x2b shift + +# +# QWERTY third row +# +less 0x56 +greater 0x56 shift +bar 0x56 altgr +mu 0x32 altgr +comma 0x33 +semicolon 0x33 shift +period 0x34 +colon 0x34 shift +minus 0x35 +underscore 0x35 shift + diff --git a/tools/ioemu/keymaps/th b/tools/ioemu/keymaps/th new file mode 100644 index 0000000000..b65b6da5d9 --- /dev/null +++ b/tools/ioemu/keymaps/th @@ -0,0 +1,131 @@ +# generated from XKB map th +include common +map 0x41e +exclam 0x02 shift +Thai_lakkhangyao 0x02 altgr +plus 0x02 shift altgr +at 0x03 shift +slash 0x03 altgr +Thai_leknung 0x03 shift altgr +numbersign 0x04 shift +minus 0x04 altgr +Thai_leksong 0x04 shift altgr +dollar 0x05 shift +Thai_phosamphao 0x05 altgr +Thai_leksam 0x05 shift altgr +percent 0x06 shift +Thai_thothung 0x06 altgr +Thai_leksi 0x06 shift altgr +asciicircum 0x07 shift +Thai_sarau 0x07 altgr +Thai_sarauu 0x07 shift altgr +ampersand 0x08 shift +Thai_saraue 0x08 altgr +Thai_baht 0x08 shift altgr +asterisk 0x09 shift +Thai_khokhwai 0x09 altgr +Thai_lekha 0x09 shift altgr +parenleft 0x0a shift +Thai_totao 0x0a altgr +Thai_lekhok 0x0a shift altgr +parenright 0x0b shift +Thai_chochan 0x0b altgr +Thai_lekchet 0x0b shift altgr +minus 0x0c +underscore 0x0c shift +Thai_khokhai 0x0c altgr +Thai_lekpaet 0x0c shift altgr +equal 0x0d +plus 0x0d shift +Thai_chochang 0x0d altgr +Thai_lekkao 0x0d shift altgr +Thai_maiyamok 0x10 altgr +Thai_leksun 0x10 shift altgr +Thai_saraaimaimalai 0x11 altgr +quotedbl 0x11 shift altgr +Thai_saraam 0x12 altgr +Thai_dochada 0x12 shift altgr +Thai_phophan 0x13 altgr +Thai_thonangmontho 0x13 shift altgr +Thai_saraa 0x14 altgr +Thai_thothong 0x14 shift altgr +Thai_maihanakat 0x15 altgr +Thai_nikhahit 0x15 shift altgr +Thai_saraii 0x16 altgr +Thai_maitri 0x16 shift altgr +Thai_rorua 0x17 altgr +Thai_nonen 0x17 shift altgr +Thai_nonu 0x18 altgr +Thai_paiyannoi 0x18 shift altgr +Thai_yoyak 0x19 altgr +Thai_yoying 0x19 shift altgr +bracketleft 0x1a +braceleft 0x1a shift +Thai_bobaimai 0x1a altgr +Thai_thothan 0x1a shift altgr +bracketright 0x1b +braceright 0x1b shift +Thai_loling 0x1b altgr +comma 0x1b shift altgr +Thai_fofan 0x1e altgr +Thai_ru 0x1e shift altgr +Thai_hohip 0x1f altgr +Thai_khorakhang 0x1f shift altgr +Thai_kokai 0x20 altgr +Thai_topatak 0x20 shift altgr +Thai_dodek 0x21 altgr +Thai_sarao 0x21 shift altgr +Thai_sarae 0x22 altgr +Thai_chochoe 0x22 shift altgr +Thai_maitho 0x23 altgr +Thai_maitaikhu 0x23 shift altgr +Thai_maiek 0x24 altgr +Thai_maichattawa 0x24 shift altgr +Thai_saraaa 0x25 altgr +Thai_sorusi 0x25 shift altgr +Thai_sosua 0x26 altgr +Thai_sosala 0x26 shift altgr +semicolon 0x27 +colon 0x27 shift +Thai_wowaen 0x27 altgr +Thai_soso 0x27 shift altgr +apostrophe 0x28 +quotedbl 0x28 shift +Thai_ngongu 0x28 altgr +period 0x28 shift altgr +grave 0x29 +asciitilde 0x29 shift +underscore 0x29 altgr +percent 0x29 shift altgr +ISO_First_Group 0x2a shift +backslash 0x2b +bar 0x2b shift +Thai_khokhuat 0x2b altgr +Thai_khokhon 0x2b shift altgr +Thai_phophung 0x2c altgr +parenleft 0x2c shift altgr +Thai_popla 0x2d altgr +parenright 0x2d shift altgr +Thai_saraae 0x2e altgr +Thai_choching 0x2e shift altgr +Thai_oang 0x2f altgr +Thai_honokhuk 0x2f shift altgr +Thai_sarai 0x30 altgr +Thai_phinthu 0x30 shift altgr +Thai_sarauee 0x31 altgr +Thai_thanthakhat 0x31 shift altgr +Thai_thothahan 0x32 altgr +question 0x32 shift altgr +comma 0x33 +less 0x33 shift +Thai_moma 0x33 altgr +Thai_thophuthao 0x33 shift altgr +period 0x34 +greater 0x34 shift +Thai_saraaimaimuan 0x34 altgr +Thai_lochula 0x34 shift altgr +slash 0x35 +question 0x35 shift +Thai_fofa 0x35 altgr +Thai_lu 0x35 shift altgr +ISO_Last_Group 0x36 shift diff --git a/tools/ioemu/keymaps/tr b/tools/ioemu/keymaps/tr new file mode 100644 index 0000000000..5650e1e93f --- /dev/null +++ b/tools/ioemu/keymaps/tr @@ -0,0 +1,123 @@ +# generated from XKB map tr +include common +map 0x41f +exclam 0x02 shift +onesuperior 0x02 altgr +exclamdown 0x02 shift altgr +apostrophe 0x03 shift +at 0x03 altgr +oneeighth 0x03 shift altgr +dead_circumflex 0x04 shift +numbersign 0x04 altgr +sterling 0x04 shift altgr +plus 0x05 shift +dollar 0x05 altgr +percent 0x06 shift +onehalf 0x06 altgr +threeeighths 0x06 shift altgr +ampersand 0x07 shift +asciicircum 0x07 altgr +fiveeighths 0x07 shift altgr +slash 0x08 shift +braceleft 0x08 altgr +seveneighths 0x08 shift altgr +parenleft 0x09 shift +bracketleft 0x09 altgr +trademark 0x09 shift altgr +parenright 0x0a shift +bracketright 0x0a altgr +plusminus 0x0a shift altgr +equal 0x0b shift +braceright 0x0b altgr +degree 0x0b shift altgr +asterisk 0x0c +question 0x0c shift +backslash 0x0c altgr +questiondown 0x0c shift altgr +minus 0x0d +underscore 0x0d shift +dead_cedilla 0x0d altgr +dead_ogonek 0x0d shift altgr +at 0x10 altgr +Greek_OMEGA 0x10 shift altgr +lstroke 0x11 altgr +Lstroke 0x11 shift altgr +EuroSign 0x12 altgr +paragraph 0x13 altgr +registered 0x13 shift altgr +tslash 0x14 altgr +Tslash 0x14 shift altgr +leftarrow 0x15 altgr +yen 0x15 shift altgr +downarrow 0x16 altgr +uparrow 0x16 shift altgr +idotless 0x17 +I 0x17 shift +rightarrow 0x17 altgr +oslash 0x18 altgr +Ooblique 0x18 shift altgr +thorn 0x19 altgr +THORN 0x19 shift altgr +gbreve 0x1a +Gbreve 0x1a shift +dead_diaeresis 0x1a altgr +dead_abovering 0x1a shift altgr +udiaeresis 0x1b +Udiaeresis 0x1b shift +asciitilde 0x1b altgr +dead_macron 0x1b shift altgr +ae 0x1e altgr +AE 0x1e shift altgr +ssharp 0x1f altgr +section 0x1f shift altgr +eth 0x20 altgr +ETH 0x20 shift altgr +dstroke 0x21 altgr +ordfeminine 0x21 shift altgr +eng 0x22 altgr +ENG 0x22 shift altgr +hstroke 0x23 altgr +Hstroke 0x23 shift altgr +kra 0x25 altgr +ampersand 0x25 shift altgr +lstroke 0x26 altgr +Lstroke 0x26 shift altgr +scedilla 0x27 +Scedilla 0x27 shift +dead_acute 0x27 altgr +dead_doubleacute 0x27 shift altgr +i 0x28 +Iabovedot 0x28 shift +dead_circumflex 0x28 altgr +dead_caron 0x28 shift altgr +backslash 0x29 +quotedbl 0x29 shift +asciitilde 0x29 altgr +comma 0x2b +semicolon 0x2b shift +bar 0x2b altgr +dead_breve 0x2b shift altgr +guillemotleft 0x2c altgr +less 0x2c shift altgr +guillemotright 0x2d altgr +greater 0x2d shift altgr +cent 0x2e altgr +copyright 0x2e shift altgr +leftdoublequotemark 0x2f altgr +grave 0x2f shift altgr +rightdoublequotemark 0x30 altgr +apostrophe 0x30 shift altgr +mu 0x32 altgr +masculine 0x32 shift altgr +odiaeresis 0x33 +Odiaeresis 0x33 shift +less 0x33 altgr +multiply 0x33 shift altgr +ccedilla 0x34 +Ccedilla 0x34 shift +greater 0x34 altgr +division 0x34 shift altgr +period 0x35 +colon 0x35 shift +dead_belowdot 0x35 altgr +dead_abovedot 0x35 shift altgr diff --git a/tools/ioemu/main.c b/tools/ioemu/main.c new file mode 100644 index 0000000000..d745aed128 --- /dev/null +++ b/tools/ioemu/main.c @@ -0,0 +1,250 @@ +/* + * qemu user main + * + * Copyright (c) 2003 Fabrice Bellard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include + +#include "qemu.h" + +#define DEBUG_LOGFILE "/tmp/qemu.log" + +#ifdef __APPLE__ +#include +# define environ (*_NSGetEnviron()) +#endif + +static const char *interp_prefix = CONFIG_QEMU_PREFIX; + +#if defined(__i386__) && !defined(CONFIG_STATIC) +/* Force usage of an ELF interpreter even if it is an ELF shared + object ! */ +const char interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2"; +#endif + +/* for recent libc, we add these dummy symbols which are not declared + when generating a linked object (bug in ld ?) */ +#if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined(CONFIG_STATIC) +long __preinit_array_start[0]; +long __preinit_array_end[0]; +long __init_array_start[0]; +long __init_array_end[0]; +long __fini_array_start[0]; +long __fini_array_end[0]; +#endif + +/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so + we allocate a bigger stack. Need a better solution, for example + by remapping the process stack directly at the right place */ +unsigned long x86_stack_size = 512 * 1024; + +void gemu_log(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} +/* timers for rdtsc */ + +#if defined(__i386__) + +int64_t cpu_get_real_ticks(void) +{ + int64_t val; + asm volatile ("rdtsc" : "=A" (val)); + return val; +} + +#elif defined(__x86_64__) + +int64_t cpu_get_real_ticks(void) +{ + uint32_t low,high; + int64_t val; + asm volatile("rdtsc" : "=a" (low), "=d" (high)); + val = high; + val <<= 32; + val |= low; + return val; +} + +#else + +static uint64_t emu_time; + +int64_t cpu_get_real_ticks(void) +{ + return emu_time++; +} + +#endif + +#ifdef TARGET_I386 +/***********************************************************/ +/* CPUX86 core interface */ + +uint64_t cpu_get_tsc(CPUX86State *env) +{ + return cpu_get_real_ticks(); +} + +void cpu_loop() +{ +} +#endif + +void usage(void) +{ + printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n" + "usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n" + "Linux CPU emulator (compiled for %s emulation)\n" + "\n" + "-h print this help\n" + "-L path set the elf interpreter prefix (default=%s)\n" + "-s size set the stack size in bytes (default=%ld)\n" + "\n" + "debug options:\n" +#ifdef USE_CODE_COPY + "-no-code-copy disable code copy acceleration\n" +#endif + "-l options activate log (logfile=%s)\n" + "-p xen port number\n", + "-d xen domain id\n", + TARGET_ARCH, + interp_prefix, + x86_stack_size, + DEBUG_LOGFILE); + _exit(1); +} + +/* XXX: currently only used for async signals (see signal.c) */ +CPUState *global_env; +/* used only if single thread */ +CPUState *cpu_single_env = NULL; + +/* used to free thread contexts */ +TaskState *first_task_state; + +int main(int argc, char **argv) +{ + const char *filename; + struct target_pt_regs regs1, *regs = ®s1; + struct image_info info1, *info = &info1; + TaskState ts1, *ts = &ts1; + CPUState *env; + int optind; + const char *r; + + if (argc <= 1) + usage(); + + /* init debug */ + cpu_set_log_filename(DEBUG_LOGFILE); + cpu_set_log(0); + + optind = 1; + for(;;) { + if (optind >= argc) + break; + r = argv[optind]; + if (r[0] != '-') + break; + optind++; + r++; + if (!strcmp(r, "-")) { + break; + } else if (!strcmp(r, "l")) { + int mask; + CPULogItem *item; + + if (optind >= argc) + break; + + r = argv[optind++]; + mask = cpu_str_to_log_mask(r); + if (!mask) { + printf("Log items (comma separated):\n"); + for(item = cpu_log_items; item->mask != 0; item++) { + printf("%-10s %s\n", item->name, item->help); + } + exit(1); + } + cpu_set_log(mask); + } else if (!strcmp(r, "s")) { + r = argv[optind++]; + x86_stack_size = strtol(r, (char **)&r, 0); + if (x86_stack_size <= 0) + usage(); + if (*r == 'M') + x86_stack_size *= 1024 * 1024; + else if (*r == 'k' || *r == 'K') + x86_stack_size *= 1024; + } else if (!strcmp(r, "L")) { + interp_prefix = argv[optind++]; + } else if (!strcmp(r, "p")) { + qemu_host_page_size = atoi(argv[optind++]); + if (qemu_host_page_size == 0 || + (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) { + fprintf(stderr, "page size must be a power of two\n"); + exit(1); + } + } else +#ifdef USE_CODE_COPY + if (!strcmp(r, "no-code-copy")) { + code_copy_enabled = 0; + } else +#endif + { + usage(); + } + } + if (optind >= argc) + usage(); + filename = argv[optind]; + + /* Zero out regs */ + memset(regs, 0, sizeof(struct target_pt_regs)); + + /* Zero out image_info */ + memset(info, 0, sizeof(struct image_info)); + + /* Scan interp_prefix dir for replacement files. */ + init_paths(interp_prefix); + + /* NOTE: we need to init the CPU at this stage to get + qemu_host_page_size */ + env = cpu_init(); + + global_env = env; + + /* build Task State */ + memset(ts, 0, sizeof(TaskState)); + env->opaque = ts; + ts->used = 1; + env->user_mode_only = 1; + + cpu_loop(env); + /* never exits */ + return 0; +} diff --git a/tools/ioemu/memory/Makefile b/tools/ioemu/memory/Makefile deleted file mode 100644 index eb9be7da4b..0000000000 --- a/tools/ioemu/memory/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -TOPDIR= .. -CXXFLAGS=-I. -I../include -I.. -OBJS= memory.o misc_mem.o - -all: libmemory.a - -libmemory.a: $(OBJS) - $(AR) $(ARFLAGS) $@ $(OBJS) - -include $(TOPDIR)/mk/helix.mk - -install:: all diff --git a/tools/ioemu/memory/memory.cc b/tools/ioemu/memory/memory.cc deleted file mode 100644 index 286c9cc864..0000000000 --- a/tools/ioemu/memory/memory.cc +++ /dev/null @@ -1,450 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: memory.cc,v 1.27 2003/03/02 23:59:12 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - - - - - -#include "bochs.h" -#define LOG_THIS BX_MEM_THIS - -#if BX_PROVIDE_CPU_MEMORY - - void BX_CPP_AttrRegparmN(3) -BX_MEM_C::writePhysicalPage(BX_CPU_C *cpu, dma_addr_t addr, unsigned len, void *data) -{ - Bit8u *data_ptr; - Bit32u a20addr; - - // Note: accesses should always be contained within a single page now. - -#if BX_IODEBUG_SUPPORT - bx_iodebug_c::mem_write(cpu, addr, len, data); -#endif - if (addr+len > this->dma_limit) - BX_PANIC(("address too large: %lx > %lx", addr+len, this->dma_limit)); - - a20addr = A20ADDR(addr); - BX_INSTR_PHY_WRITE(cpu->which_cpu(), a20addr, len); - -#if BX_DEBUGGER - // (mch) Check for physical write break points, TODO - // (bbd) Each breakpoint should have an associated CPU#, TODO - for (int i = 0; i < num_write_watchpoints; i++) - if (write_watchpoint[i] == a20addr) { - BX_CPU(0)->watchpoint = a20addr; - BX_CPU(0)->break_point = BREAK_POINT_WRITE; - break; - } -#endif - -#if BX_SupportICache - if (a20addr < BX_MEM_THIS len) - cpu->iCache.decWriteStamp(cpu, a20addr); -#endif - - if ( a20addr <= BX_MEM_THIS len ) { - // all of data is within limits of physical memory - if ( (a20addr & 0xfff80000) != 0x00080000 ) { - if (len == 4) { - WriteHostDWordToLittleEndian(&vector[a20addr], *(Bit32u*)data); - BX_DBG_DIRTY_PAGE(a20addr >> 12); - return; - } - if (len == 2) { - WriteHostWordToLittleEndian(&vector[a20addr], *(Bit16u*)data); - BX_DBG_DIRTY_PAGE(a20addr >> 12); - return; - } - if (len == 1) { - * ((Bit8u *) (&vector[a20addr])) = * (Bit8u *) data; - BX_DBG_DIRTY_PAGE(a20addr >> 12); - return; - } - // len == other, just fall thru to special cases handling - } - -#ifdef BX_LITTLE_ENDIAN - data_ptr = (Bit8u *) data; -#else // BX_BIG_ENDIAN - data_ptr = (Bit8u *) data + (len - 1); -#endif - -write_one: - if ( (a20addr & 0xfff80000) != 0x00080000 ) { - // addr *not* in range 00080000 .. 000FFFFF - vector[a20addr] = *data_ptr; - BX_DBG_DIRTY_PAGE(a20addr >> 12); -inc_one: - if (len == 1) return; - len--; - a20addr++; -#ifdef BX_LITTLE_ENDIAN - data_ptr++; -#else // BX_BIG_ENDIAN - data_ptr--; -#endif - goto write_one; - } - - // addr in range 00080000 .. 000FFFFF - - if (a20addr <= 0x0009ffff) { - // regular memory 80000 .. 9FFFF - vector[a20addr] = *data_ptr; - BX_DBG_DIRTY_PAGE(a20addr >> 12); - goto inc_one; - } - if (a20addr <= 0x000bffff) { - // VGA memory A0000 .. BFFFF - DEV_vga_mem_write(a20addr, *data_ptr); - BX_DBG_DIRTY_PAGE(a20addr >> 12); - BX_DBG_UCMEM_REPORT(a20addr, 1, BX_WRITE, *data_ptr); // obsolete - goto inc_one; - } - // adapter ROM C0000 .. DFFFF - // ROM BIOS memory E0000 .. FFFFF - // (ignore write) - //BX_INFO(("ROM lock %08x: len=%u", - // (unsigned) a20addr, (unsigned) len)); -#if BX_PCI_SUPPORT == 0 -#if BX_SHADOW_RAM - // Write it since its in shadow RAM - vector[a20addr] = *data_ptr; - BX_DBG_DIRTY_PAGE(a20addr >> 12); -#else - // ignore write to ROM -#endif -#else - // Write Based on 440fx Programming - if (bx_options.Oi440FXSupport->get () && - ((a20addr >= 0xC0000) && (a20addr <= 0xFFFFF))) { - switch (DEV_pci_wr_memtype(a20addr & 0xFC000)) { - case 0x1: // Writes to ShadowRAM -// BX_INFO(("Writing to ShadowRAM %08x, len %u ! ", (unsigned) a20addr, (unsigned) len)); - shadow[a20addr - 0xc0000] = *data_ptr; - BX_DBG_DIRTY_PAGE(a20addr >> 12); - goto inc_one; - - case 0x0: // Writes to ROM, Inhibit - BX_DEBUG(("Write to ROM ignored: address %08x, data %02x", (unsigned) a20addr, *data_ptr)); - goto inc_one; - default: - BX_PANIC(("writePhysicalPage: default case")); - goto inc_one; - } - } -#endif - goto inc_one; - } - - else { - // some or all of data is outside limits of physical memory - unsigned i; - -#ifdef BX_LITTLE_ENDIAN - data_ptr = (Bit8u *) data; -#else // BX_BIG_ENDIAN - data_ptr = (Bit8u *) data + (len - 1); -#endif - - -#if BX_SUPPORT_VBE - // Check VBE LFB support - - if ((a20addr >= VBE_DISPI_LFB_PHYSICAL_ADDRESS) && - (a20addr < (VBE_DISPI_LFB_PHYSICAL_ADDRESS + VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES))) - { - for (i = 0; i < len; i++) { - - //if (a20addr < BX_MEM_THIS len) { - //vector[a20addr] = *data_ptr; - //BX_DBG_DIRTY_PAGE(a20addr >> 12); - DEV_vga_mem_write(a20addr, *data_ptr); - // } - - // otherwise ignore byte, since it overruns memory - addr++; - a20addr = (addr); -#ifdef BX_LITTLE_ENDIAN - data_ptr++; -#else // BX_BIG_ENDIAN - data_ptr--; -#endif - } - return; - } - -#endif - - -#if BX_SUPPORT_APIC - bx_generic_apic_c *local_apic = &cpu->local_apic; - bx_generic_apic_c *ioapic = bx_devices.ioapic; - if (local_apic->is_selected (a20addr, len)) { - local_apic->write (a20addr, (Bit32u *)data, len); - return; - } else if (ioapic->is_selected (a20addr, len)) { - ioapic->write (a20addr, (Bit32u *)data, len); - return; - } - else -#endif - for (i = 0; i < len; i++) { - if (a20addr < BX_MEM_THIS len) { - vector[a20addr] = *data_ptr; - BX_DBG_DIRTY_PAGE(a20addr >> 12); - } - // otherwise ignore byte, since it overruns memory - addr++; - a20addr = (addr); -#ifdef BX_LITTLE_ENDIAN - data_ptr++; -#else // BX_BIG_ENDIAN - data_ptr--; -#endif - } - return; - } -} - - - void BX_CPP_AttrRegparmN(3) -BX_MEM_C::readPhysicalPage(BX_CPU_C *cpu, dma_addr_t addr, unsigned len, void *data) -{ - Bit8u *data_ptr; - Bit32u a20addr; - -#if BX_IODEBUG_SUPPORT - bx_iodebug_c::mem_read(cpu, addr, len, data); -#endif - - if (addr+len > this->dma_limit) - BX_PANIC(("address too large: %lx > %lx", addr+len, this->dma_limit)); - - a20addr = A20ADDR(addr); - BX_INSTR_PHY_READ(cpu->which_cpu(), a20addr, len); - -#if BX_DEBUGGER - // (mch) Check for physical read break points, TODO - // (bbd) Each breakpoint should have an associated CPU#, TODO - for (int i = 0; i < num_read_watchpoints; i++) - if (read_watchpoint[i] == a20addr) { - BX_CPU(0)->watchpoint = a20addr; - BX_CPU(0)->break_point = BREAK_POINT_READ; - break; - } -#endif - - if ( (a20addr + len) <= BX_MEM_THIS len ) { - // all of data is within limits of physical memory - if ( (a20addr & 0xfff80000) != 0x00080000 ) { - if (len == 4) { - ReadHostDWordFromLittleEndian(&vector[a20addr], * (Bit32u*) data); - return; - } - if (len == 2) { - ReadHostWordFromLittleEndian(&vector[a20addr], * (Bit16u*) data); - return; - } - if (len == 1) { - * (Bit8u *) data = * ((Bit8u *) (&vector[a20addr])); - return; - } - // len == 3 case can just fall thru to special cases handling - } - - -#ifdef BX_LITTLE_ENDIAN - data_ptr = (Bit8u *) data; -#else // BX_BIG_ENDIAN - data_ptr = (Bit8u *) data + (len - 1); -#endif - - - -read_one: - if ( (a20addr & 0xfff80000) != 0x00080000 ) { - // addr *not* in range 00080000 .. 000FFFFF - *data_ptr = vector[a20addr]; -inc_one: - if (len == 1) return; - len--; - a20addr++; -#ifdef BX_LITTLE_ENDIAN - data_ptr++; -#else // BX_BIG_ENDIAN - data_ptr--; -#endif - goto read_one; - } - - // addr in range 00080000 .. 000FFFFF -#if BX_PCI_SUPPORT == 0 - if ((a20addr <= 0x0009ffff) || (a20addr >= 0x000c0000) ) { - // regular memory 80000 .. 9FFFF, C0000 .. F0000 - *data_ptr = vector[a20addr]; - goto inc_one; - } - // VGA memory A0000 .. BFFFF - *data_ptr = DEV_vga_mem_read(a20addr); - BX_DBG_UCMEM_REPORT(a20addr, 1, BX_READ, *data_ptr); // obsolete - goto inc_one; -#else // #if BX_PCI_SUPPORT == 0 - if (a20addr <= 0x0009ffff) { - *data_ptr = vector[a20addr]; - goto inc_one; - } - if (a20addr <= 0x000BFFFF) { - // VGA memory A0000 .. BFFFF - *data_ptr = DEV_vga_mem_read(a20addr); - BX_DBG_UCMEM_REPORT(a20addr, 1, BX_READ, *data_ptr); - goto inc_one; - } - - // a20addr in C0000 .. FFFFF - if (!bx_options.Oi440FXSupport->get ()) { - *data_ptr = vector[a20addr]; - goto inc_one; - } - else { - switch (DEV_pci_rd_memtype(a20addr & 0xFC000)) { - case 0x1: // Read from ShadowRAM - *data_ptr = shadow[a20addr - 0xc0000]; - BX_INFO(("Reading from ShadowRAM %08x, Data %02x ", (unsigned) a20addr, *data_ptr)); - goto inc_one; - - case 0x0: // Read from ROM - *data_ptr = vector[a20addr]; - //BX_INFO(("Reading from ROM %08x, Data %02x ", (unsigned) a20addr, *data_ptr)); - goto inc_one; - default: - BX_PANIC(("::readPhysicalPage: default case")); - } - } - goto inc_one; -#endif // #if BX_PCI_SUPPORT == 0 - } - else { - // some or all of data is outside limits of physical memory - unsigned i; - -#ifdef BX_LITTLE_ENDIAN - data_ptr = (Bit8u *) data; -#else // BX_BIG_ENDIAN - data_ptr = (Bit8u *) data + (len - 1); -#endif - -#if BX_SUPPORT_VBE - // Check VBE LFB support - - if ((a20addr >= VBE_DISPI_LFB_PHYSICAL_ADDRESS) && - (a20addr < (VBE_DISPI_LFB_PHYSICAL_ADDRESS + VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES))) - { - for (i = 0; i < len; i++) { - - //if (a20addr < BX_MEM_THIS len) { - //vector[a20addr] = *data_ptr; - //BX_DBG_DIRTY_PAGE(a20addr >> 12); - *data_ptr = DEV_vga_mem_read(a20addr); - // } - - // otherwise ignore byte, since it overruns memory - addr++; - a20addr = (addr); -#ifdef BX_LITTLE_ENDIAN - data_ptr++; -#else // BX_BIG_ENDIAN - data_ptr--; -#endif - } - return; - } - -#endif - - -#if BX_SUPPORT_APIC - bx_generic_apic_c *local_apic = &cpu->local_apic; - bx_generic_apic_c *ioapic = bx_devices.ioapic; - if (local_apic->is_selected (addr, len)) { - local_apic->read (addr, data, len); - return; - } else if (ioapic->is_selected (addr, len)) { - ioapic->read (addr, data, len); - return; - } -#endif - for (i = 0; i < len; i++) { -#if BX_PCI_SUPPORT == 0 - if (a20addr < BX_MEM_THIS len) - *data_ptr = vector[a20addr]; - else - *data_ptr = 0xff; -#else // BX_PCI_SUPPORT == 0 - if (a20addr < BX_MEM_THIS len) { - if ((a20addr >= 0x000C0000) && (a20addr <= 0x000FFFFF)) { - if (!bx_options.Oi440FXSupport->get ()) - *data_ptr = vector[a20addr]; - else { - switch (DEV_pci_rd_memtype(a20addr & 0xFC000)) { - case 0x0: // Read from ROM - *data_ptr = vector[a20addr]; - //BX_INFO(("Reading from ROM %08x, Data %02x ", (unsigned) a20addr, *data_ptr)); - break; - - case 0x1: // Read from Shadow RAM - *data_ptr = shadow[a20addr - 0xc0000]; - BX_INFO(("Reading from ShadowRAM %08x, Data %02x ", (unsigned) a20addr, *data_ptr)); - break; - default: - BX_PANIC(("readPhysicalPage: default case")); - } // Switch - } - } - else { - *data_ptr = vector[a20addr]; - BX_INFO(("Reading from Norm %08x, Data %02x ", (unsigned) a20addr, *data_ptr)); - } - } - else - *data_ptr = 0xff; -#endif // BX_PCI_SUPPORT == 0 - addr++; - a20addr = (addr); -#ifdef BX_LITTLE_ENDIAN - data_ptr++; -#else // BX_BIG_ENDIAN - data_ptr--; -#endif - } - return; - } -} - -#endif // #if BX_PROVIDE_CPU_MEMORY diff --git a/tools/ioemu/memory/memory.h b/tools/ioemu/memory/memory.h deleted file mode 100644 index cc5869901e..0000000000 --- a/tools/ioemu/memory/memory.h +++ /dev/null @@ -1,104 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: memory.h,v 1.16 2003/08/05 13:19:35 cbothamy Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2001 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - -#define BX_USE_MEM_SMF 0 - -#if BX_USE_MEM_SMF -// if static member functions on, then there is only one memory -# define BX_MEM_SMF static -# define BX_MEM_THIS BX_MEM(0)-> -#else -# define BX_MEM_SMF -# define BX_MEM_THIS this-> -#endif - -#if defined(__i386__) -typedef Bit32u dma_addr_t; -#elif defined(__x86_64__) -typedef Bit64u dma_addr_t; -#endif - -// alignment of memory vector, must be a power of 2 -#define BX_MEM_VECTOR_ALIGN 4096 - -class BOCHSAPI BX_MEM_C : public logfunctions { - -public: - Bit8u *actual_vector; - Bit8u *vector; // aligned correctly - size_t len; - size_t dma_limit; - size_t megabytes; // (len in Megabytes) -#if BX_PCI_SUPPORT - Bit8u shadow[4*16*4096]; // 256k of memory -#endif -#if BX_DEBUGGER - unsigned char dbg_dirty_pages[(BX_MAX_DIRTY_PAGE_TABLE_MEGS * 1024 * 1024) / 4096]; - Bit32u dbg_count_dirty_pages () { - return (BX_MAX_DIRTY_PAGE_TABLE_MEGS * 1024 * 1024) / 4096; - } -#endif - unsigned long *page_array; /* for get_pfn_list() */ - - BX_MEM_C(void); - //BX_MEM_C(size_t memsize); - ~BX_MEM_C(void); - BX_MEM_SMF void alloc_vector_aligned (size_t bytes, size_t alignment) BX_CPP_AttrRegparmN(2); - BX_MEM_SMF void init_memory(int memsize); - BX_MEM_SMF void readPhysicalPage(BX_CPU_C *cpu, dma_addr_t addr, - unsigned len, void *data) BX_CPP_AttrRegparmN(3); - BX_MEM_SMF void writePhysicalPage(BX_CPU_C *cpu, dma_addr_t addr, - unsigned len, void *data) BX_CPP_AttrRegparmN(3); - BX_MEM_SMF void load_ROM(const char *path, Bit32u romaddress, Bit8u type); - BX_MEM_SMF Bit32u get_memory_in_k(void); -#if BX_PCI_SUPPORT - BX_MEM_SMF Bit8u* pci_fetch_ptr(Bit32u addr) BX_CPP_AttrRegparmN(1); -#endif - BX_MEM_SMF bx_bool dbg_fetch_mem(Bit32u addr, unsigned len, Bit8u *buf); - BX_MEM_SMF bx_bool dbg_set_mem(Bit32u addr, unsigned len, Bit8u *buf); - BX_MEM_SMF bx_bool dbg_crc32( - unsigned long (*f)(unsigned char *buf, int len), - Bit32u addr1, Bit32u addr2, Bit32u *crc); - BX_MEM_SMF Bit8u * getHostMemAddr(BX_CPU_C *cpu, Bit32u a20Addr, unsigned op) BX_CPP_AttrRegparmN(3); - }; - -#if BX_PROVIDE_CPU_MEMORY==1 - -#if BX_SMP_PROCESSORS==1 -BOCHSAPI extern BX_MEM_C bx_mem; -#else -BOCHSAPI extern BX_MEM_C *bx_mem_array[BX_ADDRESS_SPACES]; -#endif /* BX_SMP_PROCESSORS */ - -#endif /* BX_PROVIDE_CPU_MEMORY==1 */ - -#if BX_DEBUGGER -# define BX_DBG_DIRTY_PAGE(page) BX_MEM(0)->dbg_dirty_pages[page] = 1; -#else -# define BX_DBG_DIRTY_PAGE(page) -#endif diff --git a/tools/ioemu/memory/misc_mem.cc b/tools/ioemu/memory/misc_mem.cc deleted file mode 100644 index 5d2b678531..0000000000 --- a/tools/ioemu/memory/misc_mem.cc +++ /dev/null @@ -1,440 +0,0 @@ -///////////////////////////////////////////////////////////////////////// -// $Id: misc_mem.cc,v 1.41 2003/09/10 16:34:56 vruppert Exp $ -///////////////////////////////////////////////////////////////////////// -// -// Copyright (C) 2002 MandrakeSoft S.A. -// -// MandrakeSoft S.A. -// 43, rue d'Aboukir -// 75002 Paris - France -// http://www.linux-mandrake.com/ -// http://www.mandrakesoft.com/ -// -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2 of the License, or (at your option) any later version. -// -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - - - - - - -#include "bochs.h" -#ifdef BX_USE_VMX -extern "C" { -#include -} -#endif - -#define LOG_THIS BX_MEM(0)-> - -#if BX_PROVIDE_CPU_MEMORY - Bit32u -BX_MEM_C::get_memory_in_k(void) -{ - return(BX_MEM_THIS megabytes * 1024); -} -#endif // #if BX_PROVIDE_CPU_MEMORY - - -#if BX_PROVIDE_CPU_MEMORY - // BX_MEM_C constructor -BX_MEM_C::BX_MEM_C(void) -{ - char mem[6]; - snprintf(mem, 6, "MEM%d", BX_SIM_ID); - put(mem); - settype(MEMLOG); - - vector = NULL; - actual_vector = NULL; - len = 0; - megabytes = 0; -} -#endif // #if BX_PROVIDE_CPU_MEMORY - - - -#if BX_PROVIDE_CPU_MEMORY -void BX_CPP_AttrRegparmN(2) -BX_MEM_C::alloc_vector_aligned (size_t bytes, size_t alignment) -{ - if (actual_vector != NULL) { - BX_INFO (("freeing existing memory vector")); - delete [] actual_vector; - actual_vector = NULL; - vector = NULL; - } - Bit64u test_mask = alignment - 1; - actual_vector = new Bit8u [bytes+test_mask]; - // round address forward to nearest multiple of alignment. Alignment - // MUST BE a power of two for this to work. - unsigned long masked = ((unsigned long)(actual_vector + test_mask)) & ~test_mask; - vector = (Bit8u *)masked; - // sanity check: no lost bits during pointer conversion - BX_ASSERT (sizeof(masked) >= sizeof(vector)); - // sanity check: after realignment, everything fits in allocated space - BX_ASSERT (vector+bytes <= actual_vector+bytes+test_mask); - BX_INFO (("allocated memory at %p. after alignment, vector=%p", - actual_vector, vector)); -} -#endif - -// We can't use this because alloc_vector_aligned uses BX_INFO, but the object does not yet exists -/* -#if BX_PROVIDE_CPU_MEMORY - // BX_MEM_C constructor - -BX_MEM_C::BX_MEM_C(size_t memsize) -{ - char mem[6]; - snprintf(mem, 6, "MEM%d", BX_SIM_ID); - put(mem); - settype(MEMLOG); - - vector = NULL; - actual_vector = NULL; - alloc_vector_aligned (memsize, BX_MEM_VECTOR_ALIGN); - len = memsize; - megabytes = len / (1024*1024); -} -#endif // #if BX_PROVIDE_CPU_MEMORY -*/ - - -#if BX_PROVIDE_CPU_MEMORY -// BX_MEM_C destructor -BX_MEM_C::~BX_MEM_C(void) -{ - if (this-> vector != NULL) { - delete [] actual_vector; - actual_vector = NULL; - vector = NULL; - } - else { - BX_DEBUG(("(%u) memory not freed as it wasn't allocated!", BX_SIM_ID)); - } -} -#endif // #if BX_PROVIDE_CPU_MEMORY - - -#if BX_PROVIDE_CPU_MEMORY - void -BX_MEM_C::init_memory(int memsize) -{ - BX_DEBUG(("Init $Id: misc_mem.cc,v 1.41 2003/09/10 16:34:56 vruppert Exp $")); - // you can pass 0 if memory has been allocated already through - // the constructor, or the desired size of memory if it hasn't - // BX_INFO(("%.2fMB", (float)(BX_MEM_THIS megabytes) )); - -#ifndef BX_USE_VMX - if (BX_MEM_THIS vector == NULL) { - // memory not already allocated, do now... - alloc_vector_aligned (memsize, BX_MEM_VECTOR_ALIGN); -#endif - BX_MEM_THIS len = memsize; - BX_MEM_THIS megabytes = memsize / (1024*1024); - BX_INFO(("%.2fMB", (float)(BX_MEM_THIS megabytes) )); -#ifndef BX_USE_VMX - } -#endif - -#if BX_DEBUGGER - if (megabytes > BX_MAX_DIRTY_PAGE_TABLE_MEGS) { - BX_INFO(("Error: memory larger than dirty page table can handle")); - BX_PANIC(("Error: increase BX_MAX_DIRTY_PAGE_TABLE_MEGS")); - } -#endif - - unsigned long nr_pages = megabytes * (1024 * 1024/getpagesize()); - - if ( (page_array = (unsigned long *) - malloc(nr_pages * sizeof(unsigned long))) == NULL) - { - BX_ERROR(("Could not allocate memory")); - return; - } - - if ( xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages ) - { - BX_ERROR(("Could not get the page frame list")); - return; - } - -#define PAGE_SHIFT 12 -#define PAGE_SIZE (1 << PAGE_SHIFT) - - if ((vector = (Bit8u *) xc_map_foreign_batch(xc_handle, domid, - PROT_READ|PROT_WRITE, - page_array, - nr_pages - 1)) == 0) { - BX_ERROR(("Could not map guest physical")); - return; - } - - BX_MEM_THIS dma_limit = (nr_pages - 1) << PAGE_SHIFT; - BX_INFO(("DMA limit: %lx", BX_MEM_THIS dma_limit)); - - shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, - PROT_READ|PROT_WRITE, - page_array[nr_pages - 1]); -} -#endif // #if BX_PROVIDE_CPU_MEMORY - - -#if BX_PROVIDE_CPU_MEMORY - void - // Values for type : - // 0 : System Bios - // 1 : VGA Bios - // 2 : Optional ROM Bios -BX_MEM_C::load_ROM(const char *path, Bit32u romaddress, Bit8u type) -{ - struct stat stat_buf; - int fd, ret; - unsigned long size, offset; - - if (*path == '\0') { - if (type == 2) { - BX_PANIC(( "ROM: Optional BIOS image undefined.")); - } - else if (type == 1) { - BX_PANIC(( "ROM: VGA BIOS image undefined.")); - } - else { - BX_PANIC(( "ROM: System BIOS image undefined.")); - } - return; - } - // read in ROM BIOS image file - fd = open(path, O_RDONLY -#ifdef O_BINARY - | O_BINARY -#endif - ); - if (fd < 0) { - if (type < 2) { - BX_PANIC(( "ROM: couldn't open ROM image file '%s'.", path)); - } - else { - BX_ERROR(( "ROM: couldn't open ROM image file '%s'.", path)); - } - return; - } - ret = fstat(fd, &stat_buf); - if (ret) { - if (type < 2) { - BX_PANIC(( "ROM: couldn't stat ROM image file '%s'.", path)); - } - else { - BX_ERROR(( "ROM: couldn't stat ROM image file '%s'.", path)); - } - return; - } - - size = stat_buf.st_size; - - if ( (romaddress + size) > BX_MEM_THIS len ) { - BX_PANIC(( "ROM: ROM address range > physical memsize!")); - return; - } - - offset = 0; - while (size > 0) { - ret = read(fd, (bx_ptr_t) &BX_MEM_THIS vector[romaddress + offset], size); - if (ret <= 0) { - BX_PANIC(( "ROM: read failed on BIOS image: '%s'",path)); - } - size -= ret; - offset += ret; - } - close(fd); - BX_INFO(("rom at 0x%05x/%u ('%s')", - (unsigned) romaddress, - (unsigned) stat_buf.st_size, - path - )); -} -#endif // #if BX_PROVIDE_CPU_MEMORY - -#if BX_PCI_SUPPORT - Bit8u* BX_CPP_AttrRegparmN(1) -BX_MEM_C::pci_fetch_ptr(Bit32u addr) -{ - if (bx_options.Oi440FXSupport->get ()) { - switch (DEV_pci_rd_memtype (addr)) { - case 0x1: // Read from ShadowRAM - return (&BX_MEM_THIS shadow[addr - 0xc0000]); - - case 0x0: // Read from ROM - return (&BX_MEM_THIS vector[addr]); - default: - BX_PANIC(("pci_fetch_ptr(): default case")); - return(0); - } - } - else - return (&BX_MEM_THIS vector[addr]); -} -#endif - - -#if ( BX_DEBUGGER || BX_DISASM || BX_GDBSTUB) - bx_bool -BX_MEM_C::dbg_fetch_mem(Bit32u addr, unsigned len, Bit8u *buf) -{ - if ( (addr + len) > this->len ) { - BX_INFO(("dbg_fetch_mem out of range. 0x%x > 0x%x", - addr+len, this->len)); - return(0); // error, beyond limits of memory - } - for (; len>0; len--) { - if ( (addr & 0xfffe0000) == 0x000a0000 ) { - *buf = DEV_vga_mem_read(addr); - } - else { -#if BX_PCI_SUPPORT == 0 - *buf = vector[addr]; -#else - if ( bx_options.Oi440FXSupport->get () && - ((addr >= 0x000C0000) && (addr <= 0x000FFFFF)) ) { - switch (DEV_pci_rd_memtype (addr)) { - case 0x1: // Fetch from ShadowRAM - *buf = shadow[addr - 0xc0000]; -// BX_INFO(("Fetching from ShadowRAM %06x, len %u !", (unsigned)addr, (unsigned)len)); - break; - - case 0x0: // Fetch from ROM - *buf = vector[addr]; -// BX_INFO(("Fetching from ROM %06x, Data %02x ", (unsigned)addr, *buf)); - break; - default: - BX_PANIC(("dbg_fetch_mem: default case")); - } - } - else - *buf = vector[addr]; -#endif // #if BX_PCI_SUPPORT == 0 - } - buf++; - addr++; - } - return(1); -} -#endif - -#if BX_DEBUGGER || BX_GDBSTUB - bx_bool -BX_MEM_C::dbg_set_mem(Bit32u addr, unsigned len, Bit8u *buf) -{ - if ( (addr + len) > this->len ) { - return(0); // error, beyond limits of memory - } - for (; len>0; len--) { - if ( (addr & 0xfffe0000) == 0x000a0000 ) { - DEV_vga_mem_write(addr, *buf); - } - else - vector[addr] = *buf; - buf++; - addr++; - } - return(1); -} -#endif - - bx_bool -BX_MEM_C::dbg_crc32(unsigned long (*f)(unsigned char *buf, int len), - Bit32u addr1, Bit32u addr2, Bit32u *crc) -{ - unsigned len; - - *crc = 0; - if (addr1 > addr2) - return(0); - - if (addr2 >= this->len) { - return(0); // error, specified address past last phy mem addr - } - - len = 1 + addr2 - addr1; - *crc = f(vector + addr1, len); - - return(1); -} - - - Bit8u * BX_CPP_AttrRegparmN(3) -BX_MEM_C::getHostMemAddr(BX_CPU_C *cpu, Bit32u a20Addr, unsigned op) - // Return a host address corresponding to the guest physical memory - // address (with A20 already applied), given that the calling - // code will perform an 'op' operation. This address will be - // used for direct access to guest memory as an acceleration by - // a few instructions, like REP {MOV, INS, OUTS, etc}. - // Values of 'op' are { BX_READ, BX_WRITE, BX_RW }. - - // The other assumption is that the calling code _only_ accesses memory - // directly within the page that encompasses the address requested. -{ - if ( a20Addr >= BX_MEM_THIS len ) - return(NULL); // Error, requested addr is out of bounds. - if (op == BX_READ) { - if ( (a20Addr > 0x9ffff) && (a20Addr < 0xc0000) ) - return(NULL); // Vetoed! Mem mapped IO (VGA) -#if !BX_PCI_SUPPORT - return( (Bit8u *) & vector[a20Addr] ); -#else - else if ( (a20Addr < 0xa0000) || (a20Addr > 0xfffff) - || (!bx_options.Oi440FXSupport->get ()) ) - return( (Bit8u *) & vector[a20Addr] ); - else { - switch (DEV_pci_rd_memtype (a20Addr)) { - case 0x0: // Read from ROM - return ( (Bit8u *) & vector[a20Addr]); - case 0x1: // Read from ShadowRAM - return( (Bit8u *) & shadow[a20Addr - 0xc0000]); - default: - BX_PANIC(("getHostMemAddr(): default case")); - return(0); - } - } -#endif - } - else { // op == {BX_WRITE, BX_RW} - Bit8u *retAddr; - - if ( (a20Addr < 0xa0000) || (a20Addr > 0xfffff) ) { - retAddr = (Bit8u *) & vector[a20Addr]; - } -#if !BX_PCI_SUPPORT - else - return(NULL); // Vetoed! Mem mapped IO (VGA) and ROMs -#else - else if ( (a20Addr < 0xc0000) || (!bx_options.Oi440FXSupport->get ()) ) - return(NULL); // Vetoed! Mem mapped IO (VGA) and ROMs - else if (DEV_pci_wr_memtype (a20Addr) == 1) { - // Write to ShadowRAM - retAddr = (Bit8u *) & shadow[a20Addr - 0xc0000]; - } - else - return(NULL); // Vetoed! ROMs -#endif - -#if BX_SupportICache - cpu->iCache.decWriteStamp(cpu, a20Addr); -#endif - - return(retAddr); - } -} diff --git a/tools/ioemu/mk/helix.mk b/tools/ioemu/mk/helix.mk deleted file mode 100644 index e18eb340d2..0000000000 --- a/tools/ioemu/mk/helix.mk +++ /dev/null @@ -1,6 +0,0 @@ -CXXFLAGS += -O2 -I../../../tools/libxc -I../../../xen/include/public -clean: - $(RM) -f *.o *~ lib*.a device-model - -install:: - diff --git a/tools/ioemu/monitor.c b/tools/ioemu/monitor.c new file mode 100644 index 0000000000..dec25febaa --- /dev/null +++ b/tools/ioemu/monitor.c @@ -0,0 +1,282 @@ +/* + * QEMU monitor + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" +#include + +//#define DEBUG +//#define DEBUG_COMPLETION + +#ifndef offsetof +#define offsetof(type, field) ((size_t) &((type *)0)->field) +#endif + +/* + * Supported types: + * + * 'F' filename + * 'B' block device name + * 's' string (accept optional quote) + * 'i' integer + * '/' optional gdb-like print format (like "/10x") + * + * '?' optional type (for 'F', 's' and 'i') + * + */ + +typedef struct term_cmd_t { + const char *name; + const char *args_type; + void (*handler)(); + const char *params; + const char *help; +} term_cmd_t; + +static CharDriverState *monitor_hd; + +static term_cmd_t term_cmds[]; +static term_cmd_t info_cmds[]; + +static char term_outbuf[1024]; +static int term_outbuf_index; + +static void monitor_start_input(void); + +void term_flush(void) +{ + if (term_outbuf_index > 0) { + if(monitor_hd) + qemu_chr_write(monitor_hd, term_outbuf, term_outbuf_index); + else + fwrite(term_outbuf, term_outbuf_index, 1, stderr); + term_outbuf_index = 0; + } +} + +/* flush at every end of line or if the buffer is full */ +void term_puts(const char *str) +{ + int c; + for(;;) { + c = *str++; + if (c == '\0') + break; + term_outbuf[term_outbuf_index++] = c; + if (term_outbuf_index >= sizeof(term_outbuf) || + c == '\n') + term_flush(); + } +} + +void term_vprintf(const char *fmt, va_list ap) +{ + char buf[4096]; + vsnprintf(buf, sizeof(buf), fmt, ap); + term_puts(buf); +} + +void term_printf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + term_vprintf(fmt, ap); + va_end(ap); +} + +static int compare_cmd(const char *name, const char *list) +{ + const char *p, *pstart; + int len; + len = strlen(name); + p = list; + for(;;) { + pstart = p; + p = strchr(p, '|'); + if (!p) + p = pstart + strlen(pstart); + if ((p - pstart) == len && !memcmp(pstart, name, len)) + return 1; + if (*p == '\0') + break; + p++; + } + return 0; +} + +static void do_quit(void) +{ + extern int domid; + extern FILE* logfile; + char destroy_cmd[20]; + sprintf(destroy_cmd, "xm destroy %d", domid); + if (system(destroy_cmd) == -1) + fprintf(logfile, "%s failed.!\n", destroy_cmd); + exit(0); +} + +static term_cmd_t term_cmds[] = { + { "q|quit", "", do_quit, + "", "quit the emulator" }, + { NULL, NULL, }, +}; + +#define MAX_ARGS 16 + +static void monitor_handle_command(const char *cmdline) +{ + const char *p, *pstart, *typestr; + char *q; + int c, nb_args, len, i; + term_cmd_t *cmd; + char cmdname[256]; + void *str_allocated[MAX_ARGS]; + void *args[MAX_ARGS]; + +#ifdef DEBUG + term_printf("command='%s'\n", cmdline); +#endif + + /* extract the command name */ + p = cmdline; + q = cmdname; + while (isspace(*p)) + p++; + if (*p == '\0') + return; + pstart = p; + while (*p != '\0' && *p != '/' && !isspace(*p)) + p++; + len = p - pstart; + if (len > sizeof(cmdname) - 1) + len = sizeof(cmdname) - 1; + memcpy(cmdname, pstart, len); + cmdname[len] = '\0'; + + /* find the command */ + for(cmd = term_cmds; cmd->name != NULL; cmd++) { + if (compare_cmd(cmdname, cmd->name)) + goto found; + } + term_printf("unknown command: '%s'\n", cmdname); + return; + found: + + for(i = 0; i < MAX_ARGS; i++) + str_allocated[i] = NULL; + + /* parse the parameters */ + typestr = cmd->args_type; + nb_args = 0; + for(;;) { + c = *typestr; + if (c == '\0') + break; + typestr++; + switch(c) { + /* TODO: add more commands we need here to support vmx device model */ + case 'F': + case 'B': + case 's': + case '/': + case 'i': + case '-': + default: + term_printf("%s: unknown type '%c', we only support quit command now.\n", cmdname, c); + goto fail; + } + } + /* check that all arguments were parsed */ + while (isspace(*p)) + p++; + if (*p != '\0') { + term_printf("%s: extraneous characters at the end of line\n", + cmdname); + goto fail; + } + + switch(nb_args) { + case 0: + cmd->handler(); + break; + case 1: + cmd->handler(args[0]); + break; + case 2: + cmd->handler(args[0], args[1]); + break; + case 3: + cmd->handler(args[0], args[1], args[2]); + break; + case 4: + cmd->handler(args[0], args[1], args[2], args[3]); + break; + case 5: + cmd->handler(args[0], args[1], args[2], args[3], args[4]); + break; + case 6: + cmd->handler(args[0], args[1], args[2], args[3], args[4], args[5]); + break; + default: + term_printf("unsupported number of arguments: %d\n", nb_args); + goto fail; + } + fail: + for(i = 0; i < MAX_ARGS; i++) + qemu_free(str_allocated[i]); + return; +} + +static int term_can_read(void *opaque) +{ + return 128; +} + +static void term_read(void *opaque, const uint8_t *buf, int size) +{ + int i; + for(i = 0; i < size; i++) + readline_handle_byte(buf[i]); +} + +static void monitor_start_input(void); + +static void monitor_handle_command1(void *opaque, const char *cmdline) +{ + monitor_handle_command(cmdline); + monitor_start_input(); +} + +static void monitor_start_input(void) +{ + readline_start("(VTXen) ", 0, monitor_handle_command1, NULL); +} + +void monitor_init(CharDriverState *hd, int show_banner) +{ + monitor_hd = hd; + if (show_banner) { + term_printf("VMX device model. type 'q' to exit\n"); + } + qemu_chr_add_read_handler(hd, term_can_read, term_read, NULL); + monitor_start_input(); +} diff --git a/tools/ioemu/osdep.c b/tools/ioemu/osdep.c new file mode 100644 index 0000000000..087a5c2185 --- /dev/null +++ b/tools/ioemu/osdep.c @@ -0,0 +1,499 @@ +/* + * QEMU low level functions + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include +#include +#include +#include +#include + +#include "cpu.h" + +#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(CONFIG_USER_ONLY) + +#include +#include + +/* When not using soft mmu, libc independant functions are needed for + the CPU core because it needs to use alternates stacks and + libc/thread incompatibles settings */ + +#include + +#define QEMU_SYSCALL0(name) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name)); \ +return __res; \ +} + +#define QEMU_SYSCALL1(name,arg1) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1))); \ +return __res; \ +} + +#define QEMU_SYSCALL2(name,arg1,arg2) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \ +return __res; \ +} + +#define QEMU_SYSCALL3(name,arg1,arg2,arg3) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3))); \ +return __res; \ +} + +#define QEMU_SYSCALL4(name,arg1,arg2,arg3,arg4) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4))); \ +return __res; \ +} + +#define QEMU_SYSCALL5(name,arg1,arg2,arg3,arg4,arg5) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \ +return __res; \ +} + +#define QEMU_SYSCALL6(name,arg1,arg2,arg3,arg4,arg5,arg6) \ +{ \ +long __res; \ +__asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; pop %%ebp" \ + : "=a" (__res) \ + : "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \ + "0" ((long)(arg6))); \ +return __res; \ +} + +int qemu_write(int fd, const void *buf, size_t n) +{ + QEMU_SYSCALL3(write, fd, buf, n); +} + + + +/****************************************************************/ +/* shmat replacement */ + +int qemu_ipc(int call, unsigned long first, + unsigned long second, unsigned long third, + void *ptr, unsigned long fifth) +{ + QEMU_SYSCALL6(ipc, call, first, second, third, ptr, fifth); +} + +#define SHMAT 21 + +/* we must define shmat so that a specific address will be used when + mapping the X11 ximage */ +void *shmat(int shmid, const void *shmaddr, int shmflg) +{ + void *ptr; + int ret; + /* we give an address in the right memory area */ + if (!shmaddr) + shmaddr = get_mmap_addr(8192 * 1024); + ret = qemu_ipc(SHMAT, shmid, shmflg, (unsigned long)&ptr, (void *)shmaddr, 0); + if (ret < 0) + return NULL; + return ptr; +} + +/****************************************************************/ +/* sigaction bypassing the threads */ + +static int kernel_sigaction(int signum, const struct qemu_sigaction *act, + struct qemu_sigaction *oldact, + int sigsetsize) +{ + QEMU_SYSCALL4(rt_sigaction, signum, act, oldact, sigsetsize); +} + +int qemu_sigaction(int signum, const struct qemu_sigaction *act, + struct qemu_sigaction *oldact) +{ + return kernel_sigaction(signum, act, oldact, 8); +} + +/****************************************************************/ +/* memory allocation */ + +//#define DEBUG_MALLOC + +#define MALLOC_BASE 0xab000000 +#define PHYS_RAM_BASE 0xac000000 + +#define MALLOC_ALIGN 16 +#define BLOCK_HEADER_SIZE 16 + +typedef struct MemoryBlock { + struct MemoryBlock *next; + unsigned long size; /* size of block, including header */ +} MemoryBlock; + +static MemoryBlock *first_free_block; +static unsigned long malloc_addr = MALLOC_BASE; + +static void *malloc_get_space(size_t size) +{ + void *ptr; + size = TARGET_PAGE_ALIGN(size); + ptr = mmap((void *)malloc_addr, size, + PROT_WRITE | PROT_READ, + MAP_PRIVATE | MAP_FIXED | MAP_ANON, -1, 0); + if (ptr == MAP_FAILED) + return NULL; + malloc_addr += size; + return ptr; +} + +void *qemu_malloc(size_t size) +{ + MemoryBlock *mb, *mb1, **pmb; + void *ptr; + size_t size1, area_size; + + if (size == 0) + return NULL; + + size = (size + BLOCK_HEADER_SIZE + MALLOC_ALIGN - 1) & ~(MALLOC_ALIGN - 1); + pmb = &first_free_block; + for(;;) { + mb = *pmb; + if (mb == NULL) + break; + if (size <= mb->size) + goto found; + pmb = &mb->next; + } + /* no big enough blocks found: get new space */ + area_size = TARGET_PAGE_ALIGN(size); + mb = malloc_get_space(area_size); + if (!mb) + return NULL; + size1 = area_size - size; + if (size1 > 0) { + /* create a new free block */ + mb1 = (MemoryBlock *)((uint8_t *)mb + size); + mb1->next = NULL; + mb1->size = size1; + *pmb = mb1; + } + goto the_end; + found: + /* a free block was found: use it */ + size1 = mb->size - size; + if (size1 > 0) { + /* create a new free block */ + mb1 = (MemoryBlock *)((uint8_t *)mb + size); + mb1->next = mb->next; + mb1->size = size1; + *pmb = mb1; + } else { + /* suppress the first block */ + *pmb = mb->next; + } + the_end: + mb->size = size; + mb->next = NULL; + ptr = ((uint8_t *)mb + BLOCK_HEADER_SIZE); +#ifdef DEBUG_MALLOC + qemu_printf("malloc: size=0x%x ptr=0x%lx\n", size, (unsigned long)ptr); +#endif + return ptr; +} + +void qemu_free(void *ptr) +{ + MemoryBlock *mb; + + if (!ptr) + return; + mb = (MemoryBlock *)((uint8_t *)ptr - BLOCK_HEADER_SIZE); + mb->next = first_free_block; + first_free_block = mb; +} + +/****************************************************************/ +/* virtual memory allocation */ + +unsigned long mmap_addr = PHYS_RAM_BASE; + +void *get_mmap_addr(unsigned long size) +{ + unsigned long addr; + addr = mmap_addr; + mmap_addr += ((size + 4095) & ~4095) + 4096; + return (void *)addr; +} + +#else + +int qemu_write(int fd, const void *buf, size_t n) +{ + int ret; + ret = write(fd, buf, n); + if (ret < 0) + return -errno; + else + return ret; +} + +void *get_mmap_addr(unsigned long size) +{ + return NULL; +} + +void qemu_free(void *ptr) +{ + free(ptr); +} + +void *qemu_malloc(size_t size) +{ + return malloc(size); +} + +#endif + +void *qemu_mallocz(size_t size) +{ + void *ptr; + ptr = qemu_malloc(size); + if (!ptr) + return NULL; + memset(ptr, 0, size); + return ptr; +} + +char *qemu_strdup(const char *str) +{ + char *ptr; + ptr = qemu_malloc(strlen(str) + 1); + if (!ptr) + return NULL; + strcpy(ptr, str); + return ptr; +} + +/****************************************************************/ +/* printf support */ + +static inline int qemu_isdigit(int c) +{ + return c >= '0' && c <= '9'; +} + +#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) + +/* from BSD ppp sources */ +int qemu_vsnprintf(char *buf, int buflen, const char *fmt, va_list args) +{ + int c, i, n; + int width, prec, fillch; + int base, len, neg; + unsigned long val = 0; + const char *f; + char *str, *buf0; + char num[32]; + static const char hexchars[] = "0123456789abcdef"; + + buf0 = buf; + --buflen; + while (buflen > 0) { + for (f = fmt; *f != '%' && *f != 0; ++f) + ; + if (f > fmt) { + len = f - fmt; + if (len > buflen) + len = buflen; + memcpy(buf, fmt, len); + buf += len; + buflen -= len; + fmt = f; + } + if (*fmt == 0) + break; + c = *++fmt; + width = prec = 0; + fillch = ' '; + if (c == '0') { + fillch = '0'; + c = *++fmt; + } + if (c == '*') { + width = va_arg(args, int); + c = *++fmt; + } else { + while (qemu_isdigit(c)) { + width = width * 10 + c - '0'; + c = *++fmt; + } + } + if (c == '.') { + c = *++fmt; + if (c == '*') { + prec = va_arg(args, int); + c = *++fmt; + } else { + while (qemu_isdigit(c)) { + prec = prec * 10 + c - '0'; + c = *++fmt; + } + } + } + /* modifiers */ + switch(c) { + case 'l': + c = *++fmt; + break; + default: + break; + } + str = 0; + base = 0; + neg = 0; + ++fmt; + switch (c) { + case 'd': + i = va_arg(args, int); + if (i < 0) { + neg = 1; + val = -i; + } else + val = i; + base = 10; + break; + case 'o': + val = va_arg(args, unsigned int); + base = 8; + break; + case 'x': + case 'X': + val = va_arg(args, unsigned int); + base = 16; + break; + case 'p': + val = (unsigned long) va_arg(args, void *); + base = 16; + neg = 2; + break; + case 's': + str = va_arg(args, char *); + break; + case 'c': + num[0] = va_arg(args, int); + num[1] = 0; + str = num; + break; + default: + *buf++ = '%'; + if (c != '%') + --fmt; /* so %z outputs %z etc. */ + --buflen; + continue; + } + if (base != 0) { + str = num + sizeof(num); + *--str = 0; + while (str > num + neg) { + *--str = hexchars[val % base]; + val = val / base; + if (--prec <= 0 && val == 0) + break; + } + switch (neg) { + case 1: + *--str = '-'; + break; + case 2: + *--str = 'x'; + *--str = '0'; + break; + } + len = num + sizeof(num) - 1 - str; + } else { + len = strlen(str); + if (prec > 0 && len > prec) + len = prec; + } + if (width > 0) { + if (width > buflen) + width = buflen; + if ((n = width - len) > 0) { + buflen -= n; + for (; n > 0; --n) + *buf++ = fillch; + } + } + if (len > buflen) + len = buflen; + memcpy(buf, str, len); + buf += len; + buflen -= len; + } + *buf = 0; + return buf - buf0; +} + +void qemu_vprintf(const char *fmt, va_list ap) +{ + char buf[1024]; + int len; + + len = qemu_vsnprintf(buf, sizeof(buf), fmt, ap); + qemu_write(1, buf, len); +} + +void qemu_printf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + qemu_vprintf(fmt, ap); + va_end(ap); +} + diff --git a/tools/ioemu/osdep.h b/tools/ioemu/osdep.h new file mode 100644 index 0000000000..f1d18202b0 --- /dev/null +++ b/tools/ioemu/osdep.h @@ -0,0 +1,50 @@ +#ifndef QEMU_OSDEP_H +#define QEMU_OSDEP_H + +#include + +int qemu_vsnprintf(char *buf, int buflen, const char *fmt, va_list args); +void qemu_vprintf(const char *fmt, va_list ap); +void qemu_printf(const char *fmt, ...); + +void *qemu_malloc(size_t size); +void *qemu_mallocz(size_t size); +void qemu_free(void *ptr); +char *qemu_strdup(const char *str); + +void *get_mmap_addr(unsigned long size); + +/* specific kludges for OS compatibility (should be moved elsewhere) */ +#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(CONFIG_USER_ONLY) + +/* disabled pthread version of longjmp which prevent us from using an + alternative signal stack */ +extern void __longjmp(jmp_buf env, int val); +#define longjmp __longjmp + +#include + +/* NOTE: it works only because the glibc sigset_t is >= kernel sigset_t */ +struct qemu_sigaction { + union { + void (*_sa_handler)(int); + void (*_sa_sigaction)(int, struct siginfo *, void *); + } _u; + unsigned long sa_flags; + void (*sa_restorer)(void); + sigset_t sa_mask; /* mask last for extensibility */ +}; + +int qemu_sigaction(int signum, const struct qemu_sigaction *act, + struct qemu_sigaction *oldact); + +#undef sigaction +#undef sa_handler +#undef sa_sigaction +#define sigaction qemu_sigaction +#define sa_handler _u._sa_handler +#define sa_sigaction _u._sa_sigaction + +#endif + +#endif diff --git a/tools/ioemu/path.c b/tools/ioemu/path.c new file mode 100644 index 0000000000..76809705a4 --- /dev/null +++ b/tools/ioemu/path.c @@ -0,0 +1,147 @@ +/* Code to mangle pathnames into those matching a given prefix. + eg. open("/lib/foo.so") => open("/usr/gnemul/i386-linux/lib/foo.so"); + + The assumption is that this area does not change. +*/ +#include +#include +#include +#include +#include +#include +#include +#include "qemu.h" + +struct pathelem +{ + /* Name of this, eg. lib */ + char *name; + /* Full path name, eg. /usr/gnemul/x86-linux/lib. */ + char *pathname; + struct pathelem *parent; + /* Children */ + unsigned int num_entries; + struct pathelem *entries[0]; +}; + +static struct pathelem *base; + +/* First N chars of S1 match S2, and S2 is N chars long. */ +static int strneq(const char *s1, unsigned int n, const char *s2) +{ + unsigned int i; + + for (i = 0; i < n; i++) + if (s1[i] != s2[i]) + return 0; + return s2[i] == 0; +} + +static struct pathelem *add_entry(struct pathelem *root, const char *name); + +static struct pathelem *new_entry(const char *root, + struct pathelem *parent, + const char *name) +{ + struct pathelem *new = malloc(sizeof(*new)); + new->name = strdup(name); + asprintf(&new->pathname, "%s/%s", root, name); + new->num_entries = 0; + return new; +} + +#define streq(a,b) (strcmp((a), (b)) == 0) + +static struct pathelem *add_dir_maybe(struct pathelem *path) +{ + DIR *dir; + + if ((dir = opendir(path->pathname)) != NULL) { + struct dirent *dirent; + + while ((dirent = readdir(dir)) != NULL) { + if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){ + path = add_entry(path, dirent->d_name); + } + } + closedir(dir); + } + return path; +} + +static struct pathelem *add_entry(struct pathelem *root, const char *name) +{ + root->num_entries++; + + root = realloc(root, sizeof(*root) + + sizeof(root->entries[0])*root->num_entries); + + root->entries[root->num_entries-1] = new_entry(root->pathname, root, name); + root->entries[root->num_entries-1] + = add_dir_maybe(root->entries[root->num_entries-1]); + return root; +} + +/* This needs to be done after tree is stabalized (ie. no more reallocs!). */ +static void set_parents(struct pathelem *child, struct pathelem *parent) +{ + unsigned int i; + + child->parent = parent; + for (i = 0; i < child->num_entries; i++) + set_parents(child->entries[i], child); +} + +void init_paths(const char *prefix) +{ + if (prefix[0] != '/' || + prefix[0] == '\0' || + !strcmp(prefix, "/")) + return; + + base = new_entry("", NULL, prefix+1); + base = add_dir_maybe(base); + if (base->num_entries == 0) { + free (base); + base = NULL; + } else { + set_parents(base, base); + } +} + +/* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */ +static const char * +follow_path(const struct pathelem *cursor, const char *name) +{ + unsigned int i, namelen; + + name += strspn(name, "/"); + namelen = strcspn(name, "/"); + + if (namelen == 0) + return cursor->pathname; + + if (strneq(name, namelen, "..")) + return follow_path(cursor->parent, name + namelen); + + if (strneq(name, namelen, ".")) + return follow_path(cursor, name + namelen); + + for (i = 0; i < cursor->num_entries; i++) + if (strneq(name, namelen, cursor->entries[i]->name)) + return follow_path(cursor->entries[i], name + namelen); + + /* Not found */ + return NULL; +} + +/* Look for path in emulation dir, otherwise return name. */ +const char *path(const char *name) +{ + /* Only do absolute paths: quick and dirty, but should mostly be OK. + Could do relative by tracking cwd. */ + if (!base || name[0] != '/') + return name; + + return follow_path(base, name) ?: name; +} diff --git a/tools/ioemu/pc-bios/Makefile b/tools/ioemu/pc-bios/Makefile new file mode 100644 index 0000000000..7ae0ff02a0 --- /dev/null +++ b/tools/ioemu/pc-bios/Makefile @@ -0,0 +1,24 @@ +# +# NOTE: only compilable with x86 cross compile tools +# +include ../config-host.mak + +DEFINES= + +TARGETS= +ifeq ($(ARCH),i386) +TARGETS+=linux_boot.bin +endif + +all: $(TARGETS) + +linux_boot.bin: linux_boot.o + ld --oformat binary -Ttext 0 -o $@ $< + chmod a-x $@ + +%.o: %.S + $(CC) $(DEFINES) -c -o $@ $< + +clean: + rm -f $(TARGETS) *.o *~ + diff --git a/tools/ioemu/pc-bios/README b/tools/ioemu/pc-bios/README new file mode 100644 index 0000000000..a10a9f0dfa --- /dev/null +++ b/tools/ioemu/pc-bios/README @@ -0,0 +1,13 @@ +- The PC BIOS comes from the Bochs project + (http://bochs.sourceforge.net/). A patch from bios.diff was applied. + +- The VGA BIOS and the Cirrus VGA BIOS come from the LGPL VGA bios + project (http://www.nongnu.org/vgabios/). + +- The PowerPC Open Hack'Ware Open Firmware Compatible BIOS is + available at http://site.voila.fr/jmayer/OpenHackWare/index.htm. + +- Proll is a GPL'd boot PROM for Sparc JavaStations + (http://people.redhat.com/zaitcev/linux/). + Applying proll.patch allows circumventing some bugs and enables + faster kernel load through a hack. diff --git a/tools/ioemu/pc-bios/bios.bin b/tools/ioemu/pc-bios/bios.bin new file mode 100644 index 0000000000000000000000000000000000000000..fe9816e0a7750e5f8a1b185f1fbf1c49bc21175c GIT binary patch literal 65536 zcmeIb34D}A(m&plOiqR*ga8pRj4&KRzyuKyCKw=&pa>DfgIys3GJ*sWlbL{u800XM z7<9dM-4zd5cYWP=*Qo67NIZg|>wyA_ihvja!!rzWi6rEj-?ys!nIj46zW?|A{r{i; znsM~J6 zecLS8cQaE6wYOqUWJT1ZNfo{N{ffcaL2z5Ni%_;$S5&`WA=l^u5u*p(9=2_Cc*N-L z__h!9`Gl}6^#kp$ZA7$fwA~lKZFHB2(Orm_ z-51rKk$r8=HrM&X7loFvTRYUGGwA?Z8^AtQ-?T0L)A}FUa8Cbpbj9sqB=G2pi|zG4 z=*%oL@=6vJFDh6%)|@^fJw45A5tgi6N8VWT$h5Rkm!(~C+2!fx^vlPlr;iLGg(BsU<2`N5myX&cedHB8T~!<%P%@`0Hb!|Aaw^^sr090ADV|$neZ? z5iaf);&S5vBVhLkF)G3mfv0NTZTOfS(ZQxqgmPmWI($(f??qU?(jE)o}IieL4oJ&_;8Yo*n{d(AnVSR_u^F67vQ+ub1)J(B__^rc}hl}Bv zV*ZFpBf>|B5t*XovYRjKd6~E@Q_M@7m==~M(lW);^l9mF=^{N-EE##j$gU&B$V`!X zx%G0%dBmvkqvX?NS6qFCdjT4fs}kQUnTzwfsYe6i8*2+U{*0p%oU69lp$^w zIpR({jTg6wT(KBWSBqQ4Jduy5OmUl-FP7kGf|xB9h^2U%D1IgKL;;>AiC+u5D8y5i zxLw>K?!r??f7f1ltym_6S%}GFCKCakrd%~etf8mj*A2gpVEDU!)b*m6u~V;@N&vGE zH;lePIOu8Ev|-Z-hQI0Q(}k0<*(0+FU>4%W%Wo7V{4^tNhJwu;F;hOlfz7D6*?4?5 zJ1u(rUOr~ibGa?@#BAy2I1T@IQl-mn#=1h_>+a&5oIE0*-GfB7J62?CU;13f-C;;{ zLE=M7nDDTR9=hV;UwGimQ>VIL%yrpXy*)VF%f75EOX->#XJmQ}QB>GkCj+~-##!q& z2$d(`Ud!QBnN0vxp@V|FFx+;Tbib%`5WIrCGrQ%7cCkO-9EZxJ@BcVKaz(-ty{5(y zkIJSU$##buv$cb*uHytZ2EoGse^0@~0Ph2OYpgSdtNJHYRp!_J5U4fOSsg31ry5Z^ zRB~;Nqo=PV76MJq_La2yN{rCp>h00q5#FwDvjEJfEdjtt6fRrz+M4?{3@XUh)jeFI zr%80H>z&=TyK4=*cGqU3kYTpwtgMJMNivK`{EAm1^!_(QIM(`;B77v#KPAG8M507k zz5PVxoJiN42JQYAbZOwhvo+ktq;&djZ*Pv-n_)5-F122SbqP_PJYJqbM z3K%F#(Zan^TdKq4?DU#pwzF&tTfj8hn;4S)PYfGJ*^8asz!SlVr8Qf7oK)@|K=Ap_ zI8~OJr1Hj9KMDm$LBRz?#4X^3wL@`SOk*?2J|_}diu9F4y2Yt%?LLB)*?eni;@1|m zQd1dV^2Wxq-WI=UxqUwB(_JB-yA<62qX~K33-IJ>%F41(AL$b4+F!YanaGFfZt@ z+VPh`Zgl~1)AM&z`LFlqANEr+k|(z4G8#Y$wZ^z>A!8gt|E6SYIZriyQKe3D%7+xy z>|2@Q#*HJt#I5@gL#YM+a{edePXfUo!-C|$MCGsW=U+_u(cB&CxCintp!_7s1W;NV zA^*3Ke_Altbj9@wKi3{V#kC)p#pztV4dD6`xE=!61_R3aQPuot18GIqe5NX6H$$oB zuOR0ITW$ylULtOK{s}7oZ~Xc1qWl-C`K8EzC*`M_UrRDl%@0Gyn-o;qe~66Ps*K_O zGP?ehj3dE1lDOrn8vj@yTw|2XZT$^Hsm5>D|3rP$f30;(tB8$pkD2{6^y8fI3H!oRB&&_uv1Rl?UmJZ<>}g@u@^ zAO_4WLR`M6c(It2HGD<^1(yQB%G9YS6a6%*Dhw{yYe68v;Zamt4W*MfZ7p?1RT(JF z(zE*x40x_>tF|qQn^`?TmAn@A5b5{S#Nd7!!pM`Oprq>iKpO{I8g_3ZTJIIAR7Wp_ zCe_8jpW7$#R{^Z=y6nfSEa(7(9>z>4#%Btnn2k_Ff25)l0kgE|u$}}X z2)SEhmBAa9Rs%iAsFdCR0gRoe&MF8EO$7Kx2cXnA*bO{^wvt#ugHxwctF(BRfwuk5DtZ9qF{VkjYSWT5Y3+F z3|vxk+L70Li+T@_8lBywqo$jK79s6*s+ z5;>|v)=6RjMq-diQU z_IvaUV9;F6__9XFKX6McH<njHuu6cB0XbkXUII=q0FjY9Qv%*405=Fa6n!^&t~IUR zj!8jN+L7H_*}5Om&G2Y3l&w44QjTPxo2#x|02W5qx`sAb)tPUU*mEs3->q18t|fvT zZP_XEM&QWKsLC5w^&A{k1(+~;5ux3)C__U_W@ff_D+3VtGD$c%*n%NMaz${S2qGB} z3?Y)l;5omKep$_GL4N^sVM-x2)(-B0E??L73PEcc|(0Jcr zzI!QOhnR6x&oWzMxvkL}7Qc3A#Om#*+z7EliIqbhMQqrWLxXt}d&$Ct+xetG-T+!1q#P%iOIe5SyPslA;TJI4oON+fw<= z?ADpuH$bl?bTIN8AdNu21LVDgbgerCP&0&i8K8v{qyZ#A^)x`UB&ZIcNPt`bO_ZP` z02KjL0?-SZ>oewdti|=r@s|{6o|M=lZLn&TST3>0TYUdG)`mij6YirJCw%`n0*X5P zLn-hLR8Mv|+0_G85afmq;v{gl7I78qdkK~|%GP}=*;>NO*8R}p?Ntr{xi4~HKmj(H z5cB|B{+7^0N+=?1qfRvvzjU0{`E84LVzpV7KZcqQ>AosGgwrFdd#ZFYr~6mOt8_G{ z6TJzk!m%aQ;CK)JKE=O-RIn%4;Bgq-R}0s=BQ5wMYpz&#tfc~0Q2Exr7R_(JfnS~5ySNerxq(%uY)V3|1v(-?*fV~Cj`nG$jlLlOvLmXIiS z0zVLpUzK~*>?N9%VmgPGZ&Y{zUNN{=Qs-hNc(ZjGKv3@lFJlLfk8l!SR>2%RB}%l3Mc zy**P!{F;H`w*5f`V+#q(Tw!^zzn}o<3W?(QcJ=lIa+%@rYwt0v-rneje-9N!xl9A) zxsb~|;sH`Ry_jPiy3FVOE^~aO?lSj42Q+$2_M*)zpJ{@R`^W>I3T8%2zp{1T!+((% z{s(}+W?+aPh5fQ0{VmWLgbwzj-WIpumMjOGcAZbvX*h{pzV3K?0_E&XlEB-ZKsh_F z1`g~>Xe@5)?7kzc-UJ9-sR>l5`Km;5%nG8_+dn}oc%H^;YcL<>xU@qd&Rg%kWwm7o z%9@7w-VPVqqQiPGu6*YA@c9pD+1e14Va%?4<_}00A)QR=v?FEP(`sVZZE3-ZEv&LC zzHHrhE#Cg+_#_E2z+nltb^uTq*TTHr2m#0T9o*P=r|G>RI zSY+ihM?mx&5Zz8hRfAbPn=C~NN5vO{peL1KH9J$tkXecVJ{$PH#K6myuA@rJl2GYa zy>VVsYFPZ5Io!>EkBNPw$BsyigUg8OcfRt5S66>EQy)q`fN3L!(Uw5v(Mn-G%GVtw zL#lQwWH#FX3gJ3UhW1&LBT1bWI&3;@RoilLakHvqOC+>jc{T>BooT6p079;vNlm| z3BFN*Z)5OSztm|Y^`!x+uT*sDB(;}@H6G65*F3_yPr!c5$kp3TkOdRICVbI^uj&VO za{kHM3RdcZndU`1ixK z^6~?gs(z5+V^)^8YgQIEFtF!w7K=ci^IS*q*g!lWl-~oXWr=}Q9{l3H<+cWPkN#N@ zilI5u0-3RyW-b%CNYt^Jr!ALrvcBAQ&T4RuEw|O<>+*JTb`6!&iS_=ra{A&!tG4e@ zplX>URr@TMwd?A6=MZUME+M7Y==+=cGSMw0Ker9-%uw6ZtF}1@iQBc!5J`@<3Bswi zF-aWulLBf~ZvG(2fYxw}Fc&rY4^V}v!qz~+9{^sg%i$SM6}C7u&2(rfeShW31Z~0B zE?ZoMEumsgqVBC-wglIlM69|>iix1W79~+UmcCyhDKw$%1HU$9x@;zREB7e5=I0(uDQgij{*ZY?g{?(W`u-p(JY6 zNf8}UDsZ~!W>dL6ytLWiF#fQ_8~%fRiEHJchisPH%WY@jI=+0S$#^GN zmnlukBv)Or{Q0Bh18b%uincFFnqIX0NwCR)MM#+Ny$l^tWlC?7()Tblbf%#CEU! znpI7<9%{Sa5`t~FPI=wa%Ilsgwb0JIw)BAE5^^XaGc1o zp(?TRTtzJV%#tA$wm}usEaWD8!^q$i6X91A^%Ad;C3<>=>5u^d8OlHz?rFwsMT($% zV@gYJs0+|j3XtToB~{pZN&$KjM;b(S@5{>aYiBzWa&i)8J5;&{dx$)qn#S20N|2)g zhgm9YreXAe0g*;sa5SkSE;JYqvz_A{4K#MfY3DyLF#{?SVP7Bw!Qc!6X(4g0ISJlN zh!4OZ!kPyL>NyFOD{HmSKZolBp7oF7&Xn6ul-a&VAY=(g+eOd{Hc|~Csk0%e25uRg zWNpCsji>+tn*+^rR+_&G;>vB`BaR>;RUA=aJ13t|)3fsFtT&nQ%mrB10&tLMf+^yW+g@(C^?+>+jjrQ*kHCIgQdAL`_%25@zk?U&|Rv!c_rX_Ze<90Mpxb2L~ z23?;ar5({;-XnXGucXdbazqa|iuRyicsy9JIBAg{MYeVDpcnTQbmt%RR&PH<2i0h* zHs|b2?dVt8+G#9CMpuPn5Uw&KjINw>WTv+Bt8Dm*Y^)AZbLiBs1B%Ral!s2R&|+(p ziU!JUM=UF?h0f%1TOBqJaA@dtVW{_n*-pWH$Y}*ha5h+iJV;PL60khCd?nX*gG-$h zDAnjM6-!HCN|IcP6Lk<|Rxr~9FzxMU8rA{R6MOwtc^RimWK{x8_q4*~gQX7I4K3UY zg~H)tKiL{x1W!eTymQ_*;=i0It>KOiY1E7@o@pX<8s(isU3@FtAC*Y4=U5qN5~za> zuRV%VCwqm{kS~}w`Xu}zsY;if6m zr^)?#f6%m0FM@)BuAWfP*VpP>HynSnotdfK z_GPvYje}aN+rN>X&eF$^^l`4L8)g=j&zz~BsSW;8+Np^4TMYPg0~B_u z3-d_>8W?Ma^=z*)R>claJ&%5}!=Mq@Y4zT570+n(tF~Pi3JHgWJHLfHx#c7$*Z5@HQ3J!Q_2pw$xtAaTQ5%%2)N3~RR9mlE>B+V3M7`^oQ}w~k^y=r?+8aCDHxuL#zRI^w z)NAK=K1P#~^!;czKz)Lthj(IDg+_D>nr{)^?w$Hf49zMhY6RZ0)8D|h&pT@1G(dwI z`1^Cg4J-pFYGA7Y%@oa^0y_b+y<=1|p#dk@q7XE2?_Jle0mq^O$;1Y08IoNTwmX!V z?H(sP%W61XEYftxB;MKGT?;R%deNPP@D3xC)mTht7j;ZFW4h4+BOR0>xlni6t!2A2 zB=5lisKr2Kj+gLw3GbmBK-jvZ26C+Hj>GPb!>}<4tBInd?;pqO-8PwvJUd5LSu*`C zrOVe{6yTC9xg0~bWA*OIl5C44>#Z!Od|e+sgS5N83el0>4gW;h-NgZ-c6Jv{L~M6^ zKi2K;6Zr(Y+fGlq-TD4;3bLK3cV|l3N`Z_HHpYRU;baT}*=Jxmwtg~=)|v1Wus~WK z@`K<>0w#L%#~qny=ErSKbi~IUnrN?&VWMbZRyRgUDuuLzRSEj4Sho+|>;Ssi7xmgj zB%T^Y;hl;<4Kd!dv%$t|VvEyF?F^iu(PK7Xe7K0y9(cr@Y#Oy1WMA%_3qj*xK@reGyPRdIRFukTz!0yAf^c6<5XwD-*NeE8uqdJ%$4zRKzLhDIdl)G5vjZomgCTkK_J$_Jx;V+sE1*4z0^>YD z5i68jC*f!@nZhb(T!vA^uTI4r0H^8W*9-_Nw{`b~Q<9em6Lw~0nMxtQ4(LHSF_TEE zfmkW-UKF_DO&lkg~l`bXZ4G zYfO~&?*yWZ{elX8PSUmVBawUnXNYtw!8CHE&GzJIPvZs zRAxr23mX;iAjw1>P_~WhoMej2tD#7D}1v>sQ3nXcA zOsTu66!Q56`b79kub^z90xg%IpBAVbCD6pe87dGO0R{0HITj(&8&6uHndq&$Oj0Y} z>vY7`5}|7^O=i@E#V(Ppw+Yb^nLqYC>s!e1|H_?U49wr*_8#=2ijqdzTTm4H5_?%% zNUsab(^qeYf-mtb>r!qrLx0t8sD*=(XbY@q3^5s8wjovP%0TlHPKgJnfA3Fw9;QbN z-gp>7wZ6o2Khk|&wnG)RWS6bB$#r;i#kF|Bt`;xYMcJ$Ar80Z^r~Ibf)+4!=gtG1S zm=7Fr^f;#0(SYO>=NZq~E{)W)v=d*@WE2xc3ud#mJe|hN2^O+Tn%HMakeuh zXoS<50J$$CdykI5TA;7QqJ6ak)$x@eUvvZxDG}&B0`WQr6Y?y_qWzAb?#EvrVEZTDfQ*|66 z$zC9kY)5Lq>0#+L>-Rp?bCJ^k14^QMWUM$vSxc}Q05CXKfFs`G(852@%4%X0((TDJ zD#o1#BUtny^<%ReN8z>G`S}t*Nw*kJT#TnnOm(F)UTO)ru3%&R9xE_G7V7@74r?L^ z`CT@PXLq!JhO_QNb^;ci*z@RMRw2GezaLgP=Qws> z;{qV^O~BU?Iu~b`{VzfhYbFyN zKi6&!E`J1%MAgTNMGNxK+jLY{qJm}e4x!3;F@dz9 zT`()i)*PmQI-QQnImc#df6+n5aMm3n93v4XD-j+*!+{^QhmG}dpH5An%PZ%2XKHr_ zgUs5JP^SfzmD#}7TW0Igv7S(C@4yg!(lE-J7@@>yqB?j7q>7?CYvi(vc!Pf12;ZMq zWlRbA&-*XWF}&mz)HI%bp=r`t56`<;>ntMlaF9D2urgtEk`g?2CvOfN%&c8ZyT&6WER$;~OnSsl3Z=gJA>!o=|ut+DuVDQ$4XF!Al8J9td`VB62uf`+k;iY%CKY=EzR z0MK9NuDAR(3|NL~JGC$x18t&A4euJ(-$Q#YS%eiqVmj%6s6n zeG?#3(bDgJl1SN4@lO&di<(A66xan>)L6iDTT~V`Sc3iygYx!Xy0Zzyi2?bbqnO6BIzA+rG2>pqxl(5qHl(<(tDv+m@He~iLFGH%*J|% zpD*I52wMk;Zj-!8RBSf^mt}A~m)b9W%|*@LKDs%h}ZM_%&5$Q%A+G*>aWw{PXhjTxxXunx6Fp>0X~Y zB7RK*KM�@%(vHed?h2HBU5o*61%~W42jg!`X+lBc8G_(s|{a)|r)ad^q78293iV z##NUqzncm9;H6rvwNBn+!D=_&ndReZHbnM`o(cqj0S2oS0|XdJwAq|QeflS|gUkX$ zPx54i(ZrNzzY$y6LAO9g3Kd$Yl!2J!CSWMRp$wjRYUN!(1W8d4sL1Okda?0M&w?_X z#kfg{G)f#b&|78v%5|gr42sEt=3Cz;2SG2|H3Z(@^)PS&&>y_5CUA%c8YY7Xg?+_i zhGPlme-Q+TrgGY{_>-T-x(l=Dr>4*ty_ngrKq}SRg{HTda5rOm+l+zuIiByDJOlW} z1Aj{;8}yd4tCo6_)Yi6jz8Ar*b6ChsZCWR!LH#ZAs_?f+F;xk{T2PB1j+d=a`wxRDGdhS`MJNIo-Kmj^(B&FO z)aag6DKGpWebc{z#beEj^X{HkKyOkmT3YCInCCg|_Pipq-I<>st9EC|h9lmD4by9X ziPe{XIkWoj*UDHbA59j?FEta9A_o zac+lh)xIwRE&J%3uH$Z9j*CI#Z-WFRcyCh5WI$4N75JJ&sSbFX#Om+9kOR}TZ>rk+ zy}%Nx2fTp4>;GB;n%z&L=F~B+mw+bsZxvvy1n|ZkjU1lB2>6LnnSqI)?(|24l4gD; z;Ph}?cQL&su5lDfS4)xp5?Z$)AG2+?yxl(QH;lfKN~K2Er<;1IHH60ErlqMp=Rb1R zo|M(n(mv~2M%TlxTWIyIEob{raK4VSzCl@O0kmz_VT|6uoJrpxBU934Hc8G+w7Tes zC6$4wSXVIv0jow&nH~p>bZ<&y7?exshybxjoF>3@lr8dv1koxtTzu zWTO#S&7<^&oxt2)!!kmPrM^A4{%yGtk&+E9(w5r~ZmMY>xN&WqH<51Oh}zP9M06-} z6mU>S<0wc5vkFo2pCt{gdizc7G3FoP=ie9n$%C}zznJO1M#R!=!r`X2=&5?~z;W?t zw6?_$>7e)|X1k8qT28iS`{O^U_ICj7g_WU3X9UZa1Z~CMArX0Z||sf zd4EA|kOyA62S#Lk#Z|9T?fQE(KKf)U%$2#)EfRq6R05NT%}uFY4^~5>fnWL?eB}DUiQGU&hT%yi(t) zT~6XLBohd{ax~6%uF~GH>_)7UBNS-Wj=zS2&_8S@H!eyc$UYqs>*lq6?9b^C-1Osu zj%wJsKoImFuDi|X#X58&hFN_mRco)CkyAfOL@%9TV$QmC5l4iktG6FXugP|=SKzfo zUT%xCmKK3uoVBc|KfbsDRDeHK8D|UX6-~3@L|i%siilF5|Gl?HtrxK`vwc%;`v#|i z+VV(HJYLs%e1iQyIdz@X6f}E^#xE5% zYLQeImrV;r^81L5n&%Zp)`cSZg~LW|heRIXuA~(wpm&V3)fHo5=j=G!k&=OYNfstH z=v}JS9#=A53zDQU#gdh_L?9#U{;7TGwzkM#7Ljv#amW+aJooS~Co- ztAM>EvMI#Ur>TqQtJvxr6y0m2L<0X9OMch$7Q(+^T`P0>@@0@+$XvEaWXI;RK_ZXH zqYjPQJ(O1FuT91(h{mZono%`PpaY;+ql!3tvs<&&#F7G#OrWJ4)M@m(`q*VDrjOTI5%ipp1?e#|Ouf&S);R{xyvgb!6vSWKLmPpw1F=?vD z<=2VHbWZnuZTNqHbLGk%nuQ*uA>xR2#hh08Mv;2gs9F2sMbuac9Iga5$9N7$yJtau z^fa~#TE@br8eT;r<%k&1HuRuKUgk~Gj{cR4fQyQx^A%WO)b>aacD5rUj1sg}f=&^L zS7wtm%Zu_IR@F^p4M;{3{Dv1R?YkTSXO#>iq;0(sunBeplSl-)T%4qR_2(c~p;pN+ z%rJ8PD3_?^$S%K0?LWw>#*4N+dW)(|3@X#MN2f$l+l`I#MDas< zl&2M3xOrby4c`>$Ifj*>NN&RfSvHPK9Lne|idi>1fu&UZ1LF}l2OF)j=>6mmFJ#eg zNo2e2m0p9p0gJ@JZ~`dZ*$IR@9;L1Mjq{Zk zpf8LKI+!;hlCA%5QZa^hzO9)D5SZEt1G9pQu{VkIA0D&;?q|R~Z zC6?h(Mhf(Zh3Axj#Q!1`7U75*6(Q=)1ae!#m?=U@f;~qt<(ZLr)Kv=?F^uN_M$N$aGg7pC;2SFH)g&bL2<~*h2t{hrgnaz1|_^w!Ko& z2vwaCf1_8@ zJFlTu!8fBdYL`+GWwrw$Ew3!bOgNWquX|#^9@g^A=Tqa>~V z&!B_0$Zju@WJiKP{UyjlpmN&*n8%IoDUt#B5YvAU$~{xU`210lwvk~IB#dVXN!t1# zu6#lxNxPRoSkqL5JXuN7@;LKNGBZzClC&Fx8S;cBNy`XgI84eilt5C<@xGG1R3~_7 zl5$88@kj~kAwhbtA0?r=&%+mZF?&a2Sm*#XF&QIqAN>jJm9B7+4DodbfyPSEn-Zk+ zwMu9V@g@7&UzLJ>NC!V6!)*ItFU;pUWMT{2&lZGEybl(H?z+#KSp-)Aizf>LoNS+D zg3?HUE2%UZ9{LzO8pOtCC8fF=X!|nGvlrW!*hf5`8s^aOeFWdN-a0-2p+d=f)xh%z zse`h7Dm>2$f2284q3_bs>x8FNcvr68eug$)zRXA#%f_jVmtHw<&G>Z2fSL5)pJvt0 zt)07d)>eGt8~@Swvp4H$@6D91ojZJjD0(y_UM#y*G5K}Q)3?0A|1H05)opLw^2BY+ zZHSN-{bxsNO-knPc{K(TEYIv%&tR}MQ|OQI&rC2& zEW%&EpyxJm0dg5p#myk^V*8XPvgY7AodzlDgl$8b$eKK-V`w64^7vvr?;rr?Lh!OY z7xH$D=Wj6_V_vDo=)t5jlT`j1f(qh#3Ey0Vii_T{dNFJvKo9^k%?G%uLXKYiS7+w-LZk$Wj^4m;0-TXAs{k-?L*PY#AJnA+$F%qjc*O;8AoAOBzU`43pX*&0^D>V6gp ztV{W)N$SSSVt75+coQf+pTj#fS$)nvis5E3M2T__o>}LC310&OSvq8Q9oV5?>v=r1 z?%RYhNoQH*XNd_9vrHtGlOe%{Sk^zsS|Bbm@G+1YXwE5niT5&DM8`J8wmLD$t!eP{=$KCl!Jc9hh&jZeLN-E{KE&+C1aq_%eG+apb=u`wD}&U3Sa1 zq*t-pXGMDYLm|-^3M|@1#G4nKYE{^8@6TQY|4k_2T*~68A+2j)U-4?E%7Z2p6nt4#HctJc&GjvsQ@jD{OmAX7!!P@&19( za2hY{?m^XMaWocWaQkcHN&OQ%C3r> zTQx5MXjtILxmDY*r#W(N)jpy$#qu0Ew`!m1c#fP~wQZCRM9!_+?+L&`4}I*T$a!CI z1ZzDKzwrIVA8LDIa;Xw>J za<*uv{@@oAk@G(4KpZ*a{3l^lH92y&X!|8d4p7k%qhwbd{3N<6Mb2mp6*))C$l0R( zCWr|~&K7ND5QrmZgbJa2IdZmWJD&hwvY)Rhay~$jb99*PfQ+0iS^_e$1%1ttGbT?5 z5IJL>bU;SVuy~4`<)n&T7e~$(tp%=#ooIr=^EJd~PaLT{@hRc?fM66&n>;53MbjqF z>m5ha6fUbc}tlV*BDJfcs}o%r1c{_rag#j z63C^i_X(p3jAroW&3D1}aPpeUX z6LvK5!@i;Z=I$VwKBvFW+Eb=++E5zKibvEOs?Ie>^KUj{abF&WB}fhFb9ZeQ8;f)b zyD8)xu<^we%n#c& zqlCP#eNGUUji!kxl=gy7K({y~Eg8ruSb`>M7Mh zKYtutR6oQj1+53E)7)gJ9~tQLsKN73gWio!KFX%x??&HH8k>~vQ4x z140<3)m)|3`!O>@AKYE;miKu)xHRap&+H8pdgn2eOml!@jr?T1@vtwX#4#Z zV1%LY<;mdHzUv$W{;B^wc{mq*;j!k*-|$$|la~5=UU;c5L6Ol|!(@EeyV*TnjT9e} zbHLd&yhMUC)>v2b$r%NmNv69&=^H~S0%0n{{Rk#-&5{LeFy3Nf7U4{++Chjf z{aL)T2@$F17#u)MAVgFL2+aR*ziS7GcrKMb&eNd_#E?|&XsKs!r299dZ+Vx1yFxWt z1{^2`OkB%~fJo|oD1qoaynaL(4Q!;nUF{eg4Ye;dCtlK{Z<+}!EV)#eP5vPqlp9 z>TEcLnmAX6Gn{9OQR5#napfuZJPs0QoCY$SE(oL}4v0aEbqQiff*45fVf=+uK)>2W zH$7@smP2(kTOf&tQi6_rVp^zOObHYrXUPQV5=`6bV%l?byS{ds5;zwRe%F_Wy*+LWylbw$pg$&dRyvPsHZ;=b@VG0r~jw@z&l+oB&^>LT(%B^ z>VBX3z_#>xO&%ct& zx}cd}4eY<$^RHp{!9D*xAkx^ouk{B|poa{}DgSp8qyK%bx!lKg*u~XMUDF{}24! zw&&-PC~bQF4H6d8^RJSyke)wK!a{m}Hwg>r`7NutjF6u1kucfwhd}^-RS*~3(DGJr z2!mg#ELJ+XMVdrV*UyWFmOAeGv;`DIIgTiG*AU1-P6DZrAgSZfam?wq4Cd|3&cO1yQ2W?zZCY+ zAp47=o;{I2>+L42g2r`kH;NLvw;N1}5O3Ebm^NC{N^jRx%CtdIkB1;_z1B-O1fyMH(bYQJ3iH&q%XZTq98 zp{8ve*h3N);=qpVfW~_9VJmxz`G2h{Id`S8yr@1CMf5oA9tWw6>G)NPuQE;?|cO|4WDA4l; zE_r~+n0w3Yah~169Wz*h)b>uC=S|^`pWX)cAE0XsdqTJq+rn1iHqbUO?^1WPDnga& z{k6YP9dezYMi;|-WwmFQoQ!<867As~jH{B4Tcej{gsh=(fmnXKlC z7Sxoq_@FaJ8dO2;;l*81{*g&r`A0N!y!Ol=$J%^OtR}`~!dBW^nLa?#ejATv9uXMJ zBr$WuvT!2*F7*c;zqdq^W$ z%WquXv^?W(`fuI?r(LIAt?N>I;I53I+gESo^Hhs{UKdpj>!js2+8(8Y!aOmWcy9oX z^`frT8SKWR|bH<)3_wY4=zg-r~o7t5h6T(Yn)8q5pbQT35T! zZJE9tSC4Z}%yx6-dFH)y|J4*g}!ddbm`#~qp} zsY>15j(Y&tN<$Z7HrjtCMkcQ%_@KO@uKfM)jVDb36uBj!1#Fz6!AVu-ahQ@Q$DKP|(}CsI{1mc;@k--h3| zhdkQ)l8|~$4CB?raa@4}`cVw+GJcNd<@^Es9OuTlD6JPicPqDr)W{H~jU$$ES~zN? zv~?VBV9}ja%zKxUYe$u3{xvdS#Hq@-9*??P5y=fHWBBD6RICnL(%8d zs@@p{UPTu&Vob`e&Q(Y^kdfXi2)Wvc3zXxkrzi~BQ6zqG0+@A9+^v>C$V(M+6_9Xu zn1hnt%WIOsL_H0|uy!Won#S(GaaSIw^i|%v{?qkCAAarODUYPS62ImqpZ6m*RAKLg z7Mf2L>s3YXkE`yD;%H+ik*Yuql8FY1t2QWblhm|qCu7sc*EMSIh7-f4oRm9-{-1W| z+qWGy-6{I{M#mZZ`BM6eM(r8ItkL~)cNWE<`$wE2c* zVcvz=GjE)sHT}UV9LZXrr)SR?v&)fLdZ>2HE@$-Y+kSOx>xW(=eLsEfol-~l(#G22 z#K@GM{c^O#n%sU-8@$hL@JyXe5PObR^NF2d4^akyo{r4Xh8@U_+R)Fl-1oH1_R&{F z;#ufByG0n?*QcB$sp#5X?d9_@JWts^TNRajlD`{~aqtjSb zvk}{Rt%o;FLN;7FLOkZs?MaGL=M!wpR83?3Vm;yD5}i#u<;sE)n8#QVaya!)mH)f(6?(_)y16N zS~Y;b-&xg!pFECprDTY*xT{53&+CPEt}Dfc)MTV4Fr@0ajhO<3(aR!tdv|^7?T_b# zWzk!`VKv`|d6SSbQ!2dX+i-8>RC!8ySF#X8+q2mHbfA8`@TM8#mT_kwO^A zy8jg!XRLX4n-+};*ZRG_5qB8TY|r7Jd0W}G(!=qv(SOFCJ1X{Wv*Y$_K~ihq`RrSU z?d)N&*B`Q1XHJX{+;L7cVNA0XG^H>9Nia>qVE;YnhOIS z2Ka5+DTr-J&h^44v|L}mTX))@wi@x5x3UwuB@Il0lkMYyVFo~T-Q zqRM%q%5kDy86TKs4BYd5?ehQlU^al^dJtl`ey=y~?)!%qnD zIv(CS6FEdH>(s%SX-?zr{`ShS3bOKb>L8o;1aIDO`XkwQp%KowRRhHhrJ5uJp=8XLm%9 z@sJsRTQYwu1iw*RYTxh?=cNz((~YQQlD#@1%nrIO;AO5dcn$%DgBxSEewz@p+YT=F zw}sF?qYT9Ts`s5;?WmUO=eOYtDojCy0wqF+c2=VO zZBn>>)lO=GhHX&h6?SOT9_LLdIkRwF25bH`u zB$lOyUzI()+&F35jEPlYfQLCRnn<7BuS=^rF`G#Qk*okokg#op>r8fP zpi={#8tBwOrv^GT(5Zn=4RmUtQv;nE=+r=`20As+sew)nbZVee1DzV^)Ig^OIyKO# zfldu{YM@gCof_!WK&J*eHPESnP7QQwpi={#8tBwOrv^GT(5Zn=4RmUtQv;nE=+r=` z20As+sew)nbZVee1DzV^)WCnE1{N)KT$wi3T$oq1s9?dO`R1a$yPSE&j#!}(MR|8j zGN<95RlL}^Ag^T6{5AhYA{!o0Rj=IRoTH7_e#(}mfsE9asZvLG*q(HRc~b7u!49(% zMUNgeZ;_+eoIfwOP4R7*JC`oWEi6QLRNYyrLw1v&k}7Mexxnc#7ud~3xl8XLKR{hq z=2)0pw1B#5Xj3ix*%n?n_rf_BEh)^;TY^5Hw;*60#m@Qj^NNexmivorL@%lh@d)$O zi4#Jq_A}fsq;+U=Nv^}pdT@Sh^rTuZY}x@%-GS z^9vT_nFpD3i{~#|#Lu}!dFFfaiVCh47s%yYx_D{9vZaCCsWXsCyY!p-;s;Kdw#)EM^S+ssQpTb z6}gVwx$~DSm|KX-?nY@Cx{eJxqiqtb<*US83Pww#{b8PqTzY- z7Z!{B+@d@31V$3Ev|y>KErc112#?5}lH3d*w-oxI@il`~@{^_d%Nz*jJ?(}ms2TTm zzmJ@hHDme>=6MAaQ$lJdIy?9JvFzDm#U!>x8pkblnLtE#E{0vBQJsfy<-ytdId(sz~Z#Z`6PtzC=b ztuc-+_+6@S&x@O9YO9Agx?6p&?YJ^%{oeJv*4MmVirapS%|HA_(?;OtpVx7V+f2GV z$`v(flB?IGNr%q4?+@G5-RS=GR}Hw(?M+5JN6CNn4di>gs|lOTF#U8eg%&n62) z2MPBGZPTs%Jew~C+t|yvG1<8BBICxpj2nN8+v_$yX{=5Wu9V)mQLV3hEHze-2jl^x zwq@}13C5}<(#@s>BdWH^%Dl!iuk`(|ByCw9u1$7tSstcMbZNKVv zDcn~b-IUGGGw>sRuf%R?2-nixTN=W&VeTzjxHb@^HqkrOYrGN>fyTQUl%p&zrt0YtHuj4>m_H(b7A7eaEH;-Y&53t zU%x;5#yi7Z-}&Z<#?{-yZo74BZG>U#s`H|@$18Rodd=+9he)ch`MP zw^HFIs5evTV!h1+PVTHbr7eB+<1pMA)%o{JG~jvTufK$>lcrMx|G&|IXVzb$MYAwC zGXEb{DJ6%8C~e}j+bNh!eJ?GPH^QZMuVzz`iMjXkp z);hbT(75;9lSY#PF+{&3IZd0VpZ~Z=u_+}->M=7Xw_l@H`j@J|)h)QSQ=h*?(VaB^ zmoz|^MjxoarO}?O7yd65*;!1d2L3;yf$SMu&W0bi&~G-SZ22*~D*A+;cAi7}xSn#H zNs(bh^$X99H=0UuA9}yp{{>h6a@fGI#6G_KbMeu7V6yM`2uy>HPdw{Fg7%R@5vvHGt83 zJCf7v?};(_V@eL}C=oe1HB6VBmXni{mMriu8PE8A46Dy-2P!SC84TrL8X>U4ss8~H zX##aksaWyeCkM~ftq^I2Y4~dv%XgT@qhKV2Ke!nl|dG0ee_ndpqd*1W@Kkqr$P)bdUDpl94^5Q?txGT(k{Q8W$W+~M$&Eolj zFHL#$9;M2rDXS)5<#y$#_Ad9N4jgt3xc?`%(neeAK=|?0fg4^>zFU5!eCMguK;n^% zyUa7}b}N-SiEj0u+33B?yq)V&uHSHd;JvGilBiPmn5SplWpF?I-h@|qS9M3rfYE!` z>}FrNz?$TLftRAs{8yDqB|q~^{};Vbl^Q(G$A9oRAOC^leEj<#{J)5uKl4zkQXe1Z z^Z(ItKK_B@eEfeo&iVg8kMsHe@Hij;zTf%M|NG;7{J%TS$N$c8KK{3l^YOoRoR9yv z$NBho9@pbv(Z>3^%DU$pmI}3Yc<%}~q*6<7RGwm=QWZ;74(sDPx%RepWZdP}G1^rL z&$bRdyPNl-${%lHjsM1pvDwX`^4Sfe%4s9JBB=t@{S`R?dsw><@a`P`zlr}}Z@t@T zQ*r?Q;f$Dh+r*f;`Rtha>X&2Y$E7hlFX2m(N1K&O)bEJ3uU0hcTEvgGGoWJm@YZiy<>g(rUd###z<+Y2hxvpNC2wgrOc+~l^Mf0z@ zvTlK@SkQFEl?&%zxky!CbJZ2s)GbusxGHq{f~)ElNzW};HBmBSe*HD`rOy0obdT5k z!~BL&#qjNU>XOCRE}FlPu`XDkYOblPpRX=Bq=``7wG4|s=3jI9Ro5)6yRv?MXyH{? zHZ8j9nnQrAnRQ-hVG|JRLAd{gcqeo%b?1-poPHV(X``;8;Ti@V`d`<~uWPmk;DATJ zbyw(tsG7$4fUzKy_GtE%%~xLagDato61l#>^|xGK)*Lv<9df{FV_L3CVRPZxr(_exM*i`3m5NC=KaYJW?FRXp*nw-${66; zX0Gl03oIx8PGH~!22Nn$1O`rE-~PGH~!2L8W_foajqWL@+B+S7Hm>;sqk z*Y-@a_+9$?3-KGH)$ygDZz;~vYr(nkPWE;;v$xw)>XsYzzU~8+DtD}b8({kFwNKff zojUP%0s|*7@c#=8EayCjo}DVkeDdsA{LHGD@bB6&4xK;O^q^p}M@m1p*a{<6rD)E;9r@3*Vi?9RYcvz>R| z^_Q9Lm&VNYugA`9`(^Wtgf`#b;g;1ExTDrpgI7>ztT=v$1-TykFDQUOqd-xYUKg8WsAg{Klgf2E!rV z&#sNkk~;Oi@|vjBIo+vqdeF?uh?)JTQ}z5T z1M%#y$H2ebZ1eE}6G3j|!U6GZvfK8F!Hnlb6`d`594lO0@pG2>B`VzXlaD z7ke$Khm1}idvT^x#)eetq9rQSLB5aNoAurp^4u@&k*niri7HP`{Xnba0xgKXx4AK+ zEhM=-#hJR@7Y>1Ei}DY_lsF@1L=|)Doolw9v6%N~6;Dvt@*9$zAnq^WKEm8i;r<`E z&*i=_@zkGV1~gcyJh#Zar~SWE=mh-a7|~RUvKcaWR`zTAphFb_zMieG?c;d}*kk>s7F4i^>I;dCYHtxprc#v>$q!uveM! zGh*N%*NhL`TbfcH=6JR|hc@;Kt{78+o@d%o&?_XUw52BL%sEa^H;VQ z(TrVHse|XF!|C#h**c}Z@imJT)da(#5lQ)1`u=P?-6c7Rg-F zoy}a2?#K-nDWAhfd*k(&%G`vod6p#4=A9zmuUFf`MX6N0DA(wgXA`S*9jOPdMxGny z!-^}#JiMW4Yn-O5BhG=ex^iI@>oZq#~~Pz2R(<={A1(+uA8Xg6rLM~ zwG&(qKBHlU&x|#l$Sr|&@IJwjnbEJp5sj<7;xQV|GFz7RtJ42a9*r|g70Q@oY~~o` zFqo}al6pztH&w0HcZa|Zd~GA}(-8c1$exkLum)UT53b!g-Ow2@R(JY=HB*m=dt*aq zFmcDb{M3!#+3^3TbDNS~Y{1Tc=>pMi>h4gb!a4vJ=$j$V9h8=9BDc22On1lQ(j8#bHHJIjD;N>ytA8;RB(Htq92utn_o+5e1r zMt=l7T8QoxUW{}AtLXX_z*@Q*ItNa%!N6aE)Jg34IG9-daZvQr(!5kk>aHHIb@;x| zFt;Piz$X}k(E6csJVWry7{(R@ll1$w|45})J!#K3umJeb} ztm&L3bIP-BM}`K3-t;^&r_LM~h%AtK7X6TBW8_4Vsh4M2%V2l_F%G1De|!y%WJ_d=px?q>b-}|F)*|pgB;Pehcz*_q7Hiyd&c0`u#^Y=mG9EM zYg-JB&$U_V&sZ$_Q2Yw>nJ>pyc+}q@mq)|b1>txN ze;{m$EvmLbzkYlYkJx_3PUV+6(9(=)>hjC${Fh&0{;o7;W<+i^n+ID=_4yWajH<55 z&Nbpi-k^QuR-^Yz%#4i1@v|#Y={!`-O^Zm%*FQ_?WvSoSK1k>e-Uj*Qvt}3lWw1t_GH8yjTAUc%FaCOoWB(P3Uw>1%@-&6) z`gXlb#V5@XTNWC9TXa#Pk^L)ed#e-JJTeZ^2ew_}*%nr*!Ni+?j)}cns8p;X=~*ql zL%6xKrA7s&#;epM!F{->vn75ZF@Tv85A}tL{kG4_`zh?{r;Gim!HOlGD8KmSD$rRD zt!AgTQFixiEw|1KO26@<^R)bO%9a}RA6MR(IeM@qKEoTEvr%Fy)zxM@a<6IIq_{6+ zls=CACiC|rvEe?x8ruqSsl+hc z`79k2fBE3k)ED31q0wX0g-6ucV*6mb9cugBDEb-u_JeVy&}-p%RZxlz0k09e&@!q| z?A&wnG<}7H4wiyLXf1>vG9YE#pCkNS8cn6dUO9IyGVHtR+;F-2D&r4^n^RlOaqqt( zWr^PJ1cfJ{_jBoE3NbZ&;c6xJA@zi|wo?|ymf1JEIqL)NBLa&#rjk8Wsm+P#_5pJY zbk*cV9@bXJi=e4-Y8!r0EU~fDh)>IiRoo7b9>C7PR~f?H(QSw>iDfL?sb=+fRCQ0j zs_Cgvwcv3czETu_uYnjxBfjqf?2JXFTNo2@3N51qPwR>OJd6FdQ{{#|Dlc523M$pF z>%|FZ7=vKas2l{nX<%o6B^|H1JyOAL-w8BQwEP3^*7EV4%GtgudPbGH+wqI ztW_O;r)>4CXD2VIRR11RacSugEJ)l^$%64J?~i8claw+|1@cv->+EljvRi^aoXL>z1UMZ%z1;% zIkwS!aFS!yshsKknZWj)xl%6Urq05yrX4=&MQMLwrMmP6i3v$t;;#YAJ_nYWz!)gA z)I~C9m1=I2zJKP=v8eEb{cN`U8rWBrswTfHvBPISzqHAkutUeQG(KtDs9(w$JjF&d zfbRI?ub8hwBN~zW#byk-T%jnFILIHH%*Dh+q%F}2=l>>VY*8i5;}rVX;Kc9(_Slye zL(AJM)l+W>?qwWRsXtsT^HbJ0=H0UXG4D=OnIBFIsTFlaw_4HP|3cOIcZz?%Ec)y( zRAPgM9q;|4_rR5(@%bw~>Kp@}lY9EGDm~-JQI=cj@puG(R%b`R_OX`EGR&owm7c7J zjNXg^qfhyaRZFYwXQNgc*DtL$8_tMTda}={^gQ}=9b0>IhcD?-CCPj>MeJ>8)G+!b z7J2e)XIy#CxN7Y=c={PTM(F7kd=NwM4dy#Ajrb+=tt2Kjdz$(@`YMmITw7;hYmN&j=p=XLw1Bd4|K3K2Hgjn|WbIT1 z_I!HYqa4}yUZ=(Z^i!$M+bFSJ+GJjT{i6N+HE8kQCrewr?+=HR7uryQPorOXB%W54 z`n_FO@Yu(?-whLEPMJs7*Zutd=SEVMfuBh0TaPlPn->CC8Er;JsPCoCc%|CXX+%By zs#3dj90$J17yLW;Tx8?(sq36NH`(KT_n!m6*lpipy!&-3(9ML++JSO@r&}=(F@8~j8ndq)0A4VMrEwLOnFw0Q(p9& zZ+4V*gr;9exrcJ^%DBpq=jPL2j>#NWrT%oL8UJn2a`hJd0@o*Eyx3IRbPPGELcmpk zj4edQ7DFdfx{|;o`sxjAsRO0(eITIcwok_|CySphdJLKf3B6aP-mMe-YTHO;u@yK~ zbdT1n+z-Dy_@TT9pW`0}zQA*z)FICG1~Ogn6NsNxCGQ6*^Y?VhKHkAC{QtSMHtu6= zQ?%U(?2N4doEL)gVsKvK;Cz$TDU>av4Bb+UZYe>xOhLC8J$0%K-4da{8H~G+Rub>WXAVdZ(z=+D??^aa$^-jM1}s4m*v#rv|C)Mj*Zv#UkFnoX6ld5Ien`%+dn<~a-a#>vMTpe8ZaBb?DpdRG+F@F2_ zeU9H3_c?P)n-|O#Ac*VXEnG%YZK36@vNWT~0od9LQ?&;oK%DpvB{xXTT z8>gR=GM@DMW)}sf)|{@+N@UKQWYCWI%X30^l$%*IC)G5wrZ~Zy6DPhuC&DxT%t^DG z15=Spf%x2C2hAJiPLlewFTA7t+x>Tx$1j*W$sA1#fIdwB+)2`pv=96dQ`)Dlv{}ad zNc+;R(eGF0E~j0}!x68dd`$fOxs#-ws2Wgamfe=QYwjdzkMdJmH_V*G8tGnX$Lz4% z?s+rI-<9yHWp8GJn@m46U87|SG`j?vMaC2(V@i-QQ;;!68#IfIi9qi&p!Z7XeHQdy z{i!lW{5pxb5i_b(WiJaIn`?d>G}}K8iVrUQYqsydRrsq?l|ECPVaGGTKk=#GJ!2A| zVV+9Bi|Tob>kj4XVV$KbgIM-kDgdA7I8wox7i(jF zvlCcl4Kt~xSWmJp$9kFBdG@X5okg!$3HYqt8#FgmRs-u;4V%UL35A^mA7KN7M;%WC zKSOJ`$huGVMO(CSwb{h@SSO>O99hSaby;}ouWj%AzotFGE%@|1bJ?P07kUJ_wE(%* zg4|k!+=?N$Oyrh@+-gT|bs)EvBA=G)Sm3STO=4*O=gVTJp??S0OWY6rD)MCt{~tWe z_SkFB*JCqn+rz7p$hk6=I6tapT_83x^A4Y;2C?Vf?!d0Z#t@!$Y_gkV?Y)KPC-Gd? z;@#(EJg@CYs*^d_LG!rKhqa#d#rm6~cAt;F?6kYI7rW%J_q&9qcz!z1B@XS_N;f^| zyt~qQx0<;QF;}V-{84{OX()BT%vGwb4nGPUL@ZCpIvtuiL;Eot-2i41TPJFXzR>djs*JnOs$ym^i6JF^iJw$di8>&b6uu;8=3W|uPHXM>?1A?a6Q7TnEBmUeQg3IG=#L7u89IFoI_-l_pN3AKgHB(7PG8dN7b_e(bl@n24k}rX_|>8OaQuWqA$ORUCJytN z316At2kw60*jj0r6E2O#%YmD|ZTfoWI>EEVhKNUgE7@;;r5SvFGi+KN_d~ zW-Wug$mEX}J9uz)rXz#@_cP!zx5MMjf-Yx6uQ}Y0;{K=7mnCgVoOHbxJKjrd)JtsC z>&8a6Is6xZ|AO#eF8r4V|9!%)kLP_o7B5A|i47oYt=O;H#vdrvzC)#&@=)S>{7n1^ zp*@MoRi*y20sSKR9Ku)lu%1PU?7o5c*~EdO7eX_&)utM3N#rSmH8PR+qPqj`nkeJy z;9m4Ygx?H)(cNm1mTzzGk0ppRB+invb3V%EdF3ac?_baJl21M##1~Y#BRpRS{ucwo zJ;md&Wh`|k^&UjO>lm$!qf9AmO>7kW7;r4Hpd2YD-$%)>$XHXcCN`G;*AdGC4@Uh@ zUbpG>p|LWz(l5A~CN_!alB(2yT&(Mg+_v#{lbNyI=11By>bsQv{)4ZU_G)<@5*Z+4 zFmwC0t`!-Lo_>t-L8txQG8gdQ6o)sBu&CJrLl$U<|(stVc@H0W~6R&Wg!X4Cw#)O*WH*M$QZC8GC3qK;D^O+T{OD$7s9T_}uB_oh7u7uv+?+ z7?i}Fq+ej^07joPZzgfpt<>?6YnLPXkiKUm(d*_I)}5Gd@+tjYybF8^nePYY9P0Xn z_K~;w@~kTL+8W-|b;U0i9AjJffqk>ggT{4z*9@b*tHtKG`S6kLEi61QIT$W| zOb2HAC^k&xF;;bjZ2EX}@-Th;c9=dkLLbl;^ZE90o3FlOn)s&miul-pY|%X;_h@s9 zalO#btIwE^ot_TY0fEcdpu9GIHevsZ9Ps2?@T2JE&>*JeX$4VuZ{kUd|$w} zNA^2%&POcGhfU(cCh=jD_zGkWB@ST62>;K0BJ1=zz+=#z4d;8MftU48b*`EBk zitp2a@6(9hTY!98r12;@J1Zx~_}}0v~2}cME>PdQ}Gek(<3zN{QKmTTi&C`)+{`eCBo| z`>}=RxIn-8hWXZ72B=aD4rr-rT zd8XhjO-|G%MaOD=jvTYwKS|n02C{ymLYjBc`N&O`tU|Vr9@eR%kI8oz8JR2h=wH9+ zY;f$zm`~VJ8b0tGWPHTu4@`FJqFWs~^vQUe3nMrvJQ_UGcU9`w58JlruO-%hWV;f) z2^_K~p;7pmn1J{q;R59$MnGH>lraagr$l^enFsoJ)+NAauhuo=q^~3NuTC|Wa5$Zhm9{83%XbAO6KjXmtB|+$LnGBUOZa8 zs?>kZKD@l6UVTCI1-J>a=S1&Mk-3y-ZvVDE`Q$uW6UggUn!j_IE5DWr?cICm=RW8y zk7s#qe}~!Nhwz4`>9n?x;kUSLJG_!3Z9(rt<2#1-B(5X+!EoE+K9{z`?*C5P8crMb zW$@I8ABw#|f4N71-KK-}hwZn3p2Ux#57xNltlR(R7O}s24nkvEkNkRNR~#P|T7VCU zPivmHX@RzoALzzIY|_&P%kd25$(>(|-eHVyj8) zsJ7H17ShYrr+J`S@Kb7Kxcb%Q5p2rTEi$hnXWO2n&emlC-VZtd`%AZWO_8>E=GrYK zHZK0X(_JU*SqI*pR6hFFc1%_3#iZcd;k!@cjS+EA|H*LC1usZmNB5b;*P55%3r&o5 zUoNmrJP6+1xaJY@E%6M&r~4~y)%MRAWf@vi#Wx=*{v!T_;M*MEulMIjygp)~_oJlnihRd*0pIb`l=5o(-%|cn=sdBt z$lM;@Tg7Hn=g<1t^Y!$QUaen- z9$r>y>(x7U3Z4(AX?JZ#V59#G*-yqk9$y%_-HScZgd;x9A* zqb?%O(w;FCYuID+;K4q{wvAG_PH`J5wE$FH67WUM6i+hsZ zlAiV6DZ~g3VuaXz-Wihnk|=*Z);=Cx4BbkfQ+v7kHQtNG7b6~`OtnkoS&odMQe{33 z9C~iV-o@vA-C9g6+osEaoQ>V~k=_%TGqumFN_XNzhZ!?^pZS6>LNA+Z?t6uIR89LM zt@s?f#SbVZ&!4$|PU<@TmDY{&PGVp`vTMT6bs4^swAK2|12Lz)$-TL1bWKLCA+%6a zPfnlnEAvy8`sED*TNh)Y{YKUfmH2QyMZgtPzS5b@!w;3u%GL4lP#0@8owYpsj>=gd zQ=_}5svzY7Ypjmf3m%G#M{7T{IE}_SpfM-sYJFT}Y^Cz8mU`50_@_5j$o#x*7qF%^ z(Ap<^Q#0=|KVKDF_NvNled+;hgRO7K__`JoTVi~I0~sH*MO)+VlQL_iT{b-S314X& z%QMQ7-@#VpJ*f|0`OM5})%Z6mBmc|bs%d2~V)^`2EpWb3^3A_!uQO*VPx6QC;dK6& z`A@uiVK7m}8u1w!;;Z^2_?v=X)~|4`)zFxGx2w@c{W9$EWjfYq^H*AYV-PEqx_J78fu-VZJny_K_G z?yu9i&))di7Y1jSvle|jc7C4Bg?E?MGkG${UXwQDIeI3;$1i@0_W<)3Vtii4q;&xI z#DTqUlWSKZdvi;l#LxRzl_h%8xJ`|!O1)6m`8ED02d8z-%zLdbD2acCq+ahWPQ8aj zR({-Vou<4}kG2E7v_0b7xhCHWF`t~dWRfLmddM&)?KNNn?JmB}!M~Q|X*kugx@XL&&n)?}) zMFno2Z2_hNY2SE4jdtMhN#6oX?^+r6z=zaPaxZnHjAuI!gUL4xyLw%Cni#sT_X&8Z ze%U_rFMF$P+FTT0 z`53JEl(FU$aqPb#I}v-`kL|9|QzGvS3w?*3XX^}G9^^Wma?DIaWX-T|T;Ee>wD&X`ead6c#pXk3Y#O7>ctw8dg?RdD?S1$AeO_lgT_JH0az}oj>`pMJqX*-TM&*S8703*58i)bT|h~m3qb0F`l zW$!^^>xHp=k>6*}WIaN!afjd!zdOIB{UYx@KKvGu`}=4+rx5yM%mc;f41TvWPN9og z!dEhH@-8w=d@E?;FVnQ0iLE2NWz_fFWAyYmdCs@%{7%|^LHr4UuXL;O$lg3F<++SeU^pdbHbaAV76m2aMSfnkR?pCgM=&np) zw^qydLjE%@u-R)DgZ`2;*q0T3HIP3YyD9r4Y}1TbNxke38yiTphV!+Q$eQ}CXG z_Y}N`?F{|3L4U+};5~A$pg&?f@E*BW&>uAH^4_*%U2lcI{B77g67$pFD`D>qYgQhi zMQa@P^8`(M)x;l%=M>rm=K*`K_=jukc)q4NJxA8#$kY0sZP4m~jh7Y3KTox^2R(Q+ zE`*QmwoB4vrk)$2H(6sCrtuXsOD)}J!JOSPKOZ~uWB=0b;q&9t$|8Y5+H&BKwZiAD zJZ+zfPJOWSb>t*Er77F1O0scmA~OR`V|;4z+002cIS4bIybZq+zchzEFp{rs5|8(p zS%Pu>-s$VMTj*<^rg404JIA2!4P!ih2zjXN;fvX8vd`>x=)15uSJQp2 z(MtT!_Y}HlOSV&%Be7n=c`17&h+#Jhok1(MU*#cYlYdNWu1ECA#a0&^Uvltlo&Leq zl4mFVV24P|4j<;pxzIB4DUS~wB6f`APb&Q85dL$4_{#RXf9`bF2{dl(nCx=HXkYH+ zR^7UovGj>NFCL|3z$f?3=^UxkIJD!}q&DuNRddkNl0h)=r`Iz$e*^2cFaEUxaSpFzY|&#o4->1 z?cARI@W^9SW{$ACgm3M55Ad}CA9DQY^s{p~|J05LE+>}x*n6&QVB8|t`kk@?p=ZkN z+%WOWqsmLUlZ$nWlh6Lx&(q$|puE?9|CWIB{!MA+5~H`A@;s+}VOn`6pK`H-*BN5FLw944)3?ZY7-yRNy`>twS~l%=eMFpQkF+aoh^(dEg^BO|M%%2V z{I8!Uk#lz0d*`yY9=TlwB+dt3%0+&$Z`B)FOU{Y?tc?BwvR*7YiuP+u!P}~Y{Xcu| zaw^tlB9k)9I^Y4?AYX+TNFL=MYyUPEdr7aaSEU~LoCE)mjc>gU4(e}NE@K$h=UtPD zqYPlz!m9^fHqcjve92K>RT6ZUs9(2 zkQG&1{@E!nao%HJ-@mSis&S7|hg`2eoflQ%v!o7qZ7J>3{M^B~a-6w+3AuL~&%L(( zRb@9#XThK-wXHB)zDt+dm;S%(jnsT(X}ZA%eKy;??hK*pDZ@JRmVV+OhWkJGC4P4+ z-?VdS5%Twu!$X`Lyiy3`>0* zH_NoVf=-FaJhsN+;{tgfI6|_|nYwp7u!Lk!Y86L|h%8<)-ljLhQsg~6BKTF#`#SE= z^LbUNhjmUm<7tF1&K1~JJu&p2l)quGb*A=MG11{U=h*ohZ+qIMH3qiO@{7u8V$5s~^^N zzTO75_yoBQM<7Og1@H>XnF+(VoF#iwamG=o@&mN%yQX|Rj?N;P`7 zJTp~pq=NXpv?YDIZBf2emuIMIsW0-%`d6-(?0S{z^n<`V6fcCIkrB6UN*fRRSJn2m z*Od=?C3j770zc3>fi>g4@K{yq!4HLw`F+pMrFih2#Or$9eFZWfzIm|8nZtB^^$)jy z<9)Or>mi<|Wv?ai~Rs?qTr z^b`JM0siD?-Mgdhv2;5YJG@xdXox9S3Vji4Qr3;wolQb(e|%ithybc|j0vS3fMmr510Z}Ln>_qw*Vt?#!SY8xINTOw}6yYD>177Vq z*4Pbu=8C_7ZOghx+pDsFU9BcQ5#X7OL)MU@+>0N$l=~XiDEyARSYX>3AI|J*_2}FU z)@!e`#(Q%3-#N1{-Cwz_1RlEE#>@Sgf*0t(iFsudFG~?0rX6q^;NAy6%n%$&+?u+` z#|)pWsR%su;pU7~+wI-=kgS&w7tHNhDeKA)KHLR^Nxg6=!_!?xtTB&V%P_icG4b3m z=PZ(2!~Rx3dmeL)okI8fwosO5kIlQf?Ys1W&Su;a!*%G^Q)v-5bz(KMEZ`lMJ$oK^ z^0CwWu-iI-_d$85tPeX+Y?Wtk+br*3XX~6H%B`VxY`KLmw&!ZGf$V+G%L2xbJo}TT zC-64IF1xMI;Xy~<{qdlK*8(ZmWgBjLVfg(&zTwcLtm%2l)p7Dm(`}~Pwj1rYEwF8- ze|!eNJ6ifZ_G5w%@}T_WLFJGK6%ahSwxpW}g}jaH=V^IQQU|(tnK8oWZ-0gHhGe{L zAHzd3E^q-aG3IyUf^&O5|ApMi^!dDhH)j=kWKMhLu@^Q^1xw+xwkMST`~CQi3ja<) zbL2cG)+vKITh4RuA!i~OgDq40KsJ5r{JPX9zY8VSuJ^-enL})Gcb}1n_Qho1 zMGy30{7~rY{<+5K=!-Le<$8E+2evqIMt5%rc{1x0=8jm~Bk&P0p^KMVW3_A(8ur`y zlfRBjoP@b7PKULPa`y~}MAY8*;r1=E0-m>HWuG}d=B$f;*7Zzwr~dW3zu) zD)A0IZ}8+f$Y|^biJ8b+rMFtsTvBXkFS;&cqwo`YZh5Z<+SvlVsq)JKr9%)TH{vFL*dj9HHtut5W|W`Y)pk`^t%fZKfVRMCI86J2-k< z>{xI(#l}PXSbHq@Y;?vF0@eUm4saJj-^8vTX$5Y^d(RC5XIFx=iQa-I__fx09y6Zs z^Z`?y11n?jbQ$Xvhx*EE@sl5i zp5;uUwd@CM-}wqS)A5T+6|583z?aZ%F~5sJ zqVI!0H^=4bTo>IwYbj!P@LclJa*4;?N=#GYllsg9p2y{RI3zaq8MnflvZpAA@!0c2 zf5hGn&+q!HV;KUI=nv)<-6ea;HWq2!WkEx|wk=$#PCZFvl*oNsE}nXsBZqPw9(K;h zux2AO{T;7+20IRTQsnFEJ!iy=f6BaTI_X%=K844K6W6cUZ1cU9kIZ`sepBV>{BkRE ziRihh2Ry$l&GS54`k3bl_PvOIT915Qj%_Eoc%$)cJNT`Tc6s0Aej{aK=iuvjSzA|6 z@Y`V1|J}3YERU`_beE2|$T$Zp()QiR9-Iu`5q%cm-YfUCT}Yfz+iE<|>)_0cj>na! z;|=sQ?J!s3%jDSSrnG*P%tuF(W6ArO^1kqces7$TJ$G)~vKLRlMT;nI3we(*6 zg$eK->#9=6=u=+o_FOqj$DH8EBsEY?4n?87M_a{GuX~I>d&l2BlQn>(Z|f^kZp-?U z9zU%AlN@<66c<1~ylu3v+$4DpcKg>8|Ma!Pe+oYFu+~wnX*5e+{EP3iDlWmNgiNS^yZ!8g#VM%Soef) z@Hc$j<nJt0(;+MwfGlx?=lZr6K-mAdIY-rJ|7mANtcV(fDntG^BTseK*b78)@6uy>(# z_F{A+uiZ8(hugSQueC|8mD6`^TG_AczP-Dgvc|Ns`<${DoH8@5%!zM%H#ucpX=RI@ z_m(?lccztTU4!h8Ib{!~l~p+J&2!40ODj9mDT_E|+tbRj?K0N}z5VUsvOC^$%ARxH z+nZMQqEmK{Q+6P&%-yfoWtXi=o69?}>9x#Xc%n(?AYt7YLU6ad==X%`JBjKKRgnE-lH}T==%n_hlcce zzfr%c*5<3&!eJiJYre|p7rV<>K|3|@OVm237Rb4m$;;Hd-M=bbfaeW&q9#?^^SiFxEA&(2`}to>8OuCGe< zUM;%W5?L!bSIFfyHwnLLlmHsmtvgVos4HEqb{HsmrkX4J78w>h#r2U-59d+WuQ zH==&z%)0JU3t5gF!e3FP5zb}oR{=NosJx$eiMxiW^}Bzr_UE;n@-sL7jhZGbVgQR* z^%*Nx^$+Xve_-#ccZTtURRiSWdB9gDV|>S^A#bsB4ymjuI5~`(mdRmc%~>gltrhSq zxxTqPlU#_uuT^a-6S+95F7 z^s>6dp8M<8Q>P63%TwrsfSEUY9cp!7jg@|`>gvAqb*Sn6>eTvFA8@NF+<(44WyyUZ z_mbBalCkjX_EqEbCGn$e?AK;(b-GtwQsEFdP(K}<^9QbXGh1a$dcWT9_Uo8*_dNK@gs;k2H^m<0H^fy8 zZWghw?c>U`VOq4F^|U-<*9EL66o~!!q&HQTZ$*B36bPr zr5#UQGh28G-k9R>Mh?93nQ~p?mO2aDhBJph>HBuWv*KSF(16y-6I7Yxzv%NO_Ls^T zWZ-?&dhBGa%b}Z~_`K(?R%#M72+Sq&eHLuVGI=KQO`by+!DNvtljpX~<9jW;p?7kY zWn98rw0l}b7k(OhnI)FR8r@|Q1H*qa@U@8rJkNQHwlAF&IAt#_<2XE5AZ{f?$b*n0 z59~PoPA6Z0v7wiD%KVzy1IqSi?R-k-e_6B5v3ZmAE5{c`#(er3yV!x6j#kOuXN^OA zOXtkZtW0fp>pewTp2G278JFaW=gjGQq!qleXV;5Q`e(hbgZKQzOZ+kq-NcXhzeHrC zErWQM_!3u$tB{L$|K1m+9G}>=ez>Bi(sa&t zi$WV^@Pp6-eA4q;TAZl@yL1HJ_yk{U8P3BJ`oteOP3BSXjeRqZKB}uyE3ONdr`EBq zuGd;Lo`Hird_!dU>`-88xOt5lJ|mm^v@^1y2a9@ExF~jaxcP?-(0btr&q^fDM?Ln3 zwap7R-}rR*bmS{IqkhMc%Agw$X>u7wg?W0dSb4Ykq?|Y+N zVxf`)y=^*tT^a#)V%$P=PX0y&oap=}a+RkDUR-=cu!VRQG8V6yV$<@%TO3;M;C+!@ zawd%MS+2aB*s7`%Yj-KLo&7ZExNi==wZzot`HvdpcUxj3y4&G9$uEYl-sjx{+Q>B( z=c#}J+AI*A#Iq2w;sU*H&VAyET^A=-e-KPu{{j0)QW4R);7RLH?8;9)n@8YI*C)gQ zg6Kf)^UC~+E|PJl&4Hd@H})y-x-n1YSnDL+MjJWlz0gjd(6RR197 zHIi4#_+DzZ)WXT&AYSDO#3Pr)nu^rI{F%hGzG&yTgY!-1=@~Kcb%l@CW3i;;T%@5b#DSH`oov`z4!!h)wdBx2YE@3S((LXl8`;6&| zXKL!RzQmX;<{A4*{8`q?7#F-j{^S)eimuW$Ww~dMtcg;GxV3)&hLPUaHkQWC72PAe z-@*F@&im&(IJIOPLTk3}UURoC?;07OmdBc>53?a{-X!;g*kU2$D@Gnnk=$?kyc|E; z?~LhpaxXarVft8EM{b)QtMc*Ojk8D&Vm8GddB*$Ra7dlHV!ax@BB{o#*rIZHe$vW( zbu#YLp4cv#gmsoAB#7X$gb>^Ejm5=Rp9KNAy^X}SR_IMk1vzC_8@i5m8l_78$ z{jvsgV5Zo5z%~WD%it0lN1ta%TML~sIg`Z@JJ7K|3>kxizZ&hgf~&TQqn{5g^B#te z%^NRhS&^YKS5Acg>s7`I)`R%p!{vqFvK;==a#CyxcxNK^S|R6!sG8`j3C5cPjd33E z5H0R;#+d2AbcoF%{Yrma@~ivdH-iiLZTIKEb|%lVR{|Hmht%VLc|VJ56qne%@_noj zYnGh(rW!lX#HeR4b?1ELt>Hw+*+qRP$BQyzJjQdr7m&Ce|lk}x^sEo~(E$M6g4(xZ=+&Fx8f6YI0e;4QY zKh7Eb8EVW*`UKbBm0#x^f5r{YGgrLDc%D+DR^6feEACL))RQrfroWt#{LysVt+!rf zne~4w=eCqrs=AYyk8chAuYa5hws_*yRCVknUPmGRK4fyqCV_g{417k^vqT4}?TmC}aDN|BKP-Yx8D z!f%*~@8ZrUV{SW^xB~jkkws$1$oWXV8Y}cwzF!?g4vB5+E8XqE7W-ay2eBX*$A{TS zL-U4AJER@6X}BGu$rFVinbYr%l$SE1ttv5J>fdC=<;tYvX z*T+kzpPC!8%CRTVWvOW+)H@`$d5%IvUORrW$UkVli!t4qR!81dZXF9d)1gK2@!fWO)X8G3y>30|DKtVk zHi_+%rxC!WBcadyG!B`zG-*iD83b^YWOaEkafDU*?-SDEPi8B_>0P$A7TID_wlc*E)KGe zr@x`$`mpiF%1LJSC5u_tGh|;LZOpK3mv!Wu`S#H-F|3RB=-6B&Fjd+PH+ST@@j2E8 z$)D~hh&QQ8W?n{2+L_ZoYLI^XP7IcB(b(VJvB;q{>esPmdUA_xGhF(jLqC$cDz+AR z+p5Ot-*D>uT*e;GUN=i%FrHsGBcAzn_>K65{9nJW+NpPg)HAlOtCf1;G3%o8Em7*} z^(N{$HuI&I5g*a{QekA1^q=TgXJK1oLyOPndr96;p1niPr!7GLOwx83a>p8EOsvsW zstZnIuR(-7#9^8OFEUE$NBpG3 zE>DQH_P52K19w3O9}8q{iTF>yov-tsNwLS}p0SNPLSMa~)|VqQ15O|J(Ej$)B(^mB zC?v*i$0O&i$ETC?H_D_>VAe5r7iMxVIAh&A)S4j}!j$)YvlT$9`lD@p?}Pny3Iz4j=cv#QZvI#&f!z zchcuT_|N5`fn%U+p*IJX^+5*~VoEyx^PEGgS%>qVJg=$Wax!^}hLq7~rqH?YsPu`> zGivIWj3+NNCUvo2+t+c9^71Mu{jWuv`DshsnPKe$21gpn=6*VscBkw1P6{6G7@ zng7>U!WT;!XRgE&evwVHH8%*&GFMadTr)TLkw=b= zVT+~vvCvaN`rOs1QG@RMK}X_e7YJN)-npP$<}tc~SROP5oDwsTwTi>btJ7#$*Ga>T z(1GTcIq&?a+~rXRZ&If5Hs_sZM=HyZe&@WCHBy;Z!_;ekcUkI(_qoxQBH$J zcz4*AoDYsORc)F~(D`jPjxUjMuD1RM=iR}XA>ZA#ep7+gKyPe>9_GbuPW@ha6^`=VDKnnH!5E4{~Wj~OXRGNnvLgQY1WemP%n0C_4zLDM)C=z5A$uEBVg1F_ft%N zr?Hm%DQ$oA{ZDHfe$P#7H%HpFae6GUe{-am&yarkFTy?&Ui!5@I!X*hd=TP0HS)b* z&VbbMV)t9&BHNt(myQphw#{kUHK=K3LZ$d5d{59CKc{I%p~MKI$nZJQ^RJxKnKf1Z zPo!9@?9+apU(RP`&v?C_gE+^l>s+L75U2mfLgE7^zi~4|zIDNOmdERF_|D)wCyVo+ zOtGyK7qEAObKVmj*wnlClRNoO0h_z|H)bZ{)W5$EqfE%Te7wPlrv}bD9Qiv z^ZNw-S!Vrj=Mmsf!#8WJ@U#Q_X~VD| z0{5A2ABVSpj5r7G1FT=zZQ5{Gz3R4^4!5&Et-wNOh>hUlPGmMR&Dpa(ymsx%Mi&l= z?>MyVoR?CyReX0R&x<{*w6hKwmOvi2tFPA7tFMa9&-YVLgT9KbH@PU&b)Hm(Qm*T5 z;P+YT_DkJAY?OH)3I3zN|)s37-sn@#Jx&F_c1u|A! zCS2H!9@a5d=3th@fhD##9XVpHe(iwu=nl?ZdToGjg4bzWf+y~062tO=yAZK%zxDWQ z1J>)*-M@qLfTeueLI+M;W&qRSIg!v;NaotbqsR;P6@{!jFk9+bAJXl7;mq{$rqQJK z9hPljuMWI$OnKGF?)+)U>}rJeUpp*?JTZ*G#fA!i-> zpt%saN(Ci;d;j<3zY}|8W?=H={PHcm$>;NX;l+WtpEGTKU&*(+`Ig>>>R7_Eze$&9 zt~C-D^2zYLuk&rX(pdcZFUR8F;VihQtXW=N$2UV`51^Os->tmFO?|}6{p1Vg@V#OA zE?I#6PXYc9@_&&3bNN4)|MQ5chj=D&^#Xk56?1y|maY0jP{tx>^Ms4;t>qhS!9=H; zl)RC6`|}cWCg*XF>?if)gqN~cE(ao3k`wMhzda|qX-_hTG4EmQFVNpT*l|l$;Ioch z^!%rdpZuAa*pOOp)N=+fcBBnUDr%}tHY^#y@)oc>#Xg5SRPeLHaX1WeX6WJb08Z&w z%f5nM?oHJvbQ9p-YpTu2xPt@4HJGc^c3XDcS1q~Pk~@~jdMeiX`$uDmyUD37;w+b6 zKH%8o7rf8>iVV^|*%D}e2{iv%bF4q%r@;?8e-Gc9_BkWxs(kcE+8Gyo7g*`_-VDx5 zS3S%*`{Vo%ysJ*tdA;v4r#7BNcITpt<*ejdqlqws??n`S4Q|`=NcS zCaS=y4E4DO?og-p)U&Vd>#7!bBeG^eodwB!Rk`db)zUqYZ}B|E`Wm#u|BXFwsd?xz@_z?DWQ~)@m8;KZ z$yQzACe`KQu&epMVeXHj6C}o>ZCLq6`(UZiLQPd_;c17_f}H6u^RIe-2F`8-XU*X3 zd2seF<9=Stlck&~uvFkqqlaqfq1qkGC+OkmdZ9(^@$N0EvU{hRwG8|%19!_RRPC}l zHE&r`MLEZ<0UdD6-!~@CR?-Gd%Gtkds4Dr!ak5o)bS3%L9p3|Jz4K?Wcw@$0t?xV< zllZ>)(eW?iOJQ5a$3kBhUlRMVN3D`rLzr^ruA}B3eC5d^dz~U)$h)-RyzkYyLC}KK z7hb}oP1VGF<%w+X(0RPAecVTZNuRM*8ICL&wMp7_eE5L0C%(ATrjF;gZv8mc+%G!h zlV@&8&g7iiFDRe0=11jomOooQXIU2Kz>S)h$o^%lIW+P+l$RxD-X8lt0FKlq<#~yX zKaPDrbfogE1FfA)V&6ypkNket>#`SDa`0Mj;9TQpABZJJJ%!yr5at{o&a%vUOvWr@ zMTRIDtBjdB&~Y%qpT_l7H&}J#{T4j0zqv#HjQ(!9=zLpV-|zTQ6_>GR!=Hqn z%qz8zqvQ-TV5@1J(G%-BnLTj{_QbuZYS8<&=>Nv#bY#i*)V%IGbkGF8TYAG=vIjqh zdNJrb$nyX+o-5yOu2hMex~>%6>XYyEah9zo1k8S5_5pK_^$~h}tbL}IQGdVV%SEh0{`&YLN2a=Xan{8m=L7Rz+E9WQ@GW*Y`wwJ|?fwoM$C3PG zDR{}|O#PG9Qef@s=Kr?+JiA`ybWTunz*TMQ1wFB49{7s6(Dd+c*gAi>9^6^az8UhEI$w7**D%kE?PhK@U27{{{L z@oB+T;*a|^t{6`iZR7|ZM4u3+%MmZJI*`zC!Ym%Wp#m2c{D;ibU?jJXloo;R(C zHIL>~}J-#i`3`gn-11J=CS_KXpKe|feV@QG#RXAjk{Kl&EFz+viP0fes|Yk zy!mvU{}OJd&H7PKFrN`AXMMYv?*QFf+Uwia&3cR2P?f6m7G#KlZt%=*8r8~vffBPJ zBj%KCfCjV;&b!1MbMKY+kZZ<$DaorzrS6}gPM34IInOhXxtt+$>F5n#$2#`6KdChOf2wx>sEBmGTT6S|zhSO(!+$N!|fIaT}wlj_#=l*rgi$8h`zPr!K<1G7J8r%VC zLtqxzjXwP?v3zsf_DODRDq3&nK=A98_slEw8u1YAx-hu!rnMb(%cT7|7qAY-*o1bW z4G(AaW%5mLpRBjAzMO-vnmm z1G{x8er^|ViEnI)4TQZj3wx&;d#46_rxu@g9zJihC!cRaR$zLSxdr65t7kSE_x+d8tCvkOh3Vda~SxU}IiEc;{ zOZoF+Ti1JbK?_Nv^O9|XPoe#;vARF;oyimVMoVJX{#e-r)d#&7nm?KtE9=kF-{xg} z_8!qX@`frn$85dI12-YYT+rHiM@(eChKuucqrXq7X($W&)%!jePa}PKvAM+ucza~{ z|Fm%!e$R|U;s4-afggSjG5!Kc#3%OQp3O#1u#bFnb-)?h-7+@TM?Bq&HU9QEW9#^= zV?*~IWo#d4`-C}JYGtT){1a?U@X0;k3C>DNlU%(zhLI|b@*R_YrRF@rx5+{(3modR zw`Go8KXlITvdZOK6Ro=*jfEo;1KYPana{o=>@Iw|9Q;?wwVsEgpSRrK!#Q#I z4RteZy<1n|tRuDyUqD;4;DKs*paveOg$L%r15tRO0Ul_C2Nu8sE%3l1cpwH3nDBt* z@IarA%jX~cn;zKqI^Ux-AD^uLff=?=|Jp-|vgdVN9eF0>_vrDzK`tD42rF>Gc!%)7 z9xsiD4e!RFpHv-j8o?8IV9)BGuTC5L(@u5FCTc0&rOfE{nls3AmgBE)8&51}-BG zF14?Xe9(J49Jm+QFn_fZ8g=8Rl1Ftw^FKJU`Csi3dyaeLq3Q=OXHAQ;j;sQogHHp{ zsULdFA@?M=%(7HjFZ0p2SC#b#)HG$OX(7I?3NFa4KWBQs<(}cI^+M0?jsSLdF73)U zXlkM5TKW=t+eZvv^6gvbZ^E=F%1;HFKiS_0^ygJ&ee|pQ`#}1$?EXG}e0u)}pP|2l z-GUb@Nlt$K1MN0$zOqo@1K0MtIQRpndY?#=H3)2?#x9@UHzoHAWDk{t@1w_L-58AQ zXJ@}I^I2Jyy3DmD-FSsQKbX9JnTG;vIA1J>Z{3oQgdT)xBE?|$iQ%Iv+99w%l~chuOe9v|~w zAhgqkd}dEwK-MAfsr}N2tcS!KE~TG`yVxrsdlrEC+p_+qV?yB3jRQwDpC?rpa(+27 zeFb#7nzrv0y@fBuoMtYOZvwY%q!0XD$wLJvdCqvZ%Xox;C4OJ2E*FM~)tt6#wGh zNi|A+wQEdjKw@HD@22)~9pGDn!LT3tzEJ(Y?7a_sRMoXVdIn}NfvEA`*ai(SsbCWg z7&PDs36Mad2@@c|AXu@?kOY_#l9&Vy?F^YA(F;%fyz4qE`@4dDa_W-_t z`$y<5ptQM{VgKZ3QxY^>6Kuf4lg`iLClD?Ql(`t96nkViWEX}L;lqHZXSja@FX+>c zpie)BKK&%{)*@)^o0o*1#1^yus4ebci!J`)WLv_+xwgcI-L|BM12)*Zw~c&ww+;60 zZE4LGTY7V{Eu%TtrZ&56+06l4PV)v^Uh{5SLGw{tQIo~yY;s$VHwCOGNiRe=CwvQA zGTWrwTKp8r2#9xD`m-$ntT*3JchY1l11tzTlNGSW_ygACE=6To5ch{;yun@K$<{bL zu!UkxP&aM26P==6QUrZEQ!~*<0k`#JwzAq1kv@*nuXp24@?_+NJdlp^7|AwWS*D(I zA`|$dbm}Xwpv@I&?_m1b2|18wK{r$&02ko@rd@;@wJ3>F+ zoeh2fyr09{O7+4w_K_if^h3ry^?l?e@|nG5vI{n>b@$BsOMYgjcJ2l~Pm>);s<$jN z6=Rz@Ze|vUmGCa`hk4zmS8`k(=`w!N3fdb)GAV_to43}g`(DXmJ5}6ncigSvo%~eb z9_>>g%DN+$(-2-c%#7DrUvn7Yi^AFglgMwa#6=FtH{h$d2iJNo(-jXHDV_05c)>Ft z^n|MZGS?ktfOJX-h@E*6NibH{0A0>8pOlujeXr#Sw$ zSC$%Z%nkT=Te~UE1h@4uq^YGiGOx0594%Ns(XLqBsp;wKlc6_J6w5@HVgbJF?q%u4 zl!wIEQVmbdxxig6aF=T>2hOU1Ghq{?2d;{_PAGp3__8h2rF<_FvK4Uu81igEc^i?( zljzgW;CTV`nMiQ1TKt5BwfHIn?xJ@EestVEV$j*N%lpRdoU@=W^=D;GLEUyRAFamtNWE>afdxT(E`v zG2!XJD;t?+^>niz*KjNQ?^Ywv*}g!smCpb`?=oP0vQ1GpqaSO1TBqR|sg%crqt?B| z1GzsN`ELuy>zzk4ldXp!6Drh~kf*g-;PQg~S=|g=Qof=;=ZJbw-(s{s#uS7b{b)M+ zh7IEea1yX~p}n0H4!p?m<@QJWraQqaXxw2s68x=Qlq+}zSpj2< z`pzp|0*^DkhzLtU*fAOQfsX%oUO6Pwu90CoDV^|>eUo9C$+(yP2}YlpX%l?zv_j*q ztoIJk%r3MO+m$Dr@p=&FGi|iiP9iUiRqQ{b4RkjIxcg_y1L=1Ff9=5iuI6Ox9^@6z zd5}y*w8v=*j|RYFXq`p%oK~o>;Lh8j8qN^!5c=`}5qIigO)jLmLoVs!@SD&%^iw80n(#IK1K@W!{CB z=(w6rs;Pe_m_T*I(Y8=&@ZBsI>IW}l@7JTW|L{r%Pq7S&JPF=^sD z+o?Y5GXM+enICvsw(ISwTAhG*a~WhKVkqZ9c$f9zbV%Rq)arEG39j#^SM8K9*?twc z$~kMMajG|91y4Xc(f2;m>qmYfT+;Y7rhn6%M9SEXQKGDE2^?P^!yT8anE&&?0#!&osj>;T~zEo0d%J2!6)@JFl9eZN2ug08uHRjZ-F{fUQIrVDHsaIo8 z-GDiD1Lo8Xm{T`kPTdf&|KSf=R)-!6jASN zS?@tcy_5GjLb)d{qTWdaGwE)$x{_XKy#w_{-MD@5?gMtA+ryqFz;Dpuigr7Jc0)dTyWtyamfUV=vvu@MYkiqFvW;p5 zYo}J6)3xG$C$d?sG(3+sL_6Z#jnZ&}_Ulb!TgF(wh&SbvN96&wj5SYT@0wK^jBuRy zy3&I2a&Un%g3hWy4|yf%WW?3ChOmwboj>%l?~6R30|E^RIMLQ97x-em9&}X+&{ZX( zz0G!6deV9C_%hRZQ%`)2IP3^b{<=T-(&-%V0iS}-SDEM>ILhwAy8Z2IGS=Pzo5gmV z-%%JZ_Qz9z^TE)eT(%}d*4ZNSi^1C(QTN{Hyl*`)^uJjx&`k~N;`7)!ex;W7FpkBZ za^HX;|MW2lWNFVY!f?ZBG#CfW@A2YFhe z<%#y(LA+0IyFPTj(040quok4@C)1_egzp8Qo0!KvAk0{-2?2M=^Q0;6O>`~>=_ri9 z(GCL){`YM=^FNCfceh(dLQY9(c3aaRXQwxBux2#xwyMoXS#Om`b5Fv#KfHg@x`dft zS|q&;F!;l;O^(pSef_5wOAEEPxsNrVZ|Qw%6UJMNkp;@_E3v*x>wxRQAPqz`u(t9i#<>Z>0ky> zdev=>qjM6No5#s^y$QIayU_v56R-R2^W1*yq|wW<2`sq zymY^d@f7)1Zy_0j7YiZBO;e=!#Xn)8F+)dARMB)J(*-fOob*#oQp1 z##%#v`L~(A*p{{m-LgSn*A_ZLS)PlaFMlL`5f5+pi{RtT!~d@cdc&N$K*8J&b_~Pl z4gR7%u6Zkh-jc9SIUe|@{z_{a<>703d@mjKoffp+Inj1oPT_2|h0cd$+L;F?IF;^I zlpcMSc>fviuxtO-+cNZ^eJ%9NjrMd(=WQH_z3Rtdn|1Sh$m>aw*JE4$vAq7L4|x@f zyzcoW?7q_70RI4NRV%qKE{mieIc9+#dKtF_|GqeSF^~6WdX8U1hdM%;nf;*`;J|f3 zS}~9JYr&hCR;GL;X(dCf^@2C)w37I^nO4l>7|L5mbfdaxE|~k4iGDJ|>4)w=Q;2@( zd>gkD+sekA+Yx#`6@FxU)@u0uYa#p+!u=|zM{5(54clh9h5DG(d)xF^rid6Lc4_yt zn#PFl-|q>otGnKY4TgU7O-GIB5N_SFHF zgOX#gzbPiM*&UPA9EgE^gc#UIh)HQa8iRcsF&Q-1Z8(87aN0Kjn}u}#f$Y?fy%ahJ zLHjg?&62TnzcJs-$vV?k%=bHXvEEvQPdFjg&UYN5@tpEbFWhwyRO?*jsE0J8TMT zQakpQn!?(&F!BRDPpTciE|zd^AX$a>)u@fTHbU+zlYNla+9mui0T<^eKBdQA%;j2s z$ZH3O8TFn;@)?~uY5pVUo$&iEL+l5`fV$AG*9ddTN= ze$Ye<gajidYJ3$5ACHo@xF`JU3(1Nsb8>8g!V5}T{bWrAJMmvX~!<-eWai@v9~A&_NZeL z8$gc@pvMN#V*}{10raRQ$4Gmr-^w`-*7gHf+uwjS`rTOTKWa^a&WiVkFwN4QmnT58 z*tuTJ! z-|M|b+F!ZqYuO%0DE|WGCf1Aj*EXEvJ676u@%|VQcI#1<+*E()%&2Vu!@HWhKuN!w zXvqT6cAE+1Sr6_KDn@tGN;HJwNct?E={yGA?8mE9Tl(%(bnUYg@Jb zG?JHyy^_stobL-nv9%I?Ot=j6Z040G<(P1pF($;{=?JB-?9Z408gA6a15L-&PzYY> z0IysK{RHM!q`O!Tp5K7C9tZqX)6Fz&#!pBi8m}Y96iM6AQ{?t-Z(BQ~8m6a;J`at+TbosmF($lSnd}JN zl-nN}19+pe9AP>O|2~PgA7lInP8e^9Mzopq~xl zwt2AsitiL89Rz5)sG${Q{6VpbzTB21`YDxp%Us<*038zMw!~A^&)P;JEYpvE>)(LA zkE{b8Zi6f%+5_c5Zv@_A?6Cv>F9-|Wk4o_9Wq#I{X25duKFzTQN6Q}+*t1$QjnJPfuR6ov<31xnJ1zG0DkH<$NTMdiJ8FOz?~Fi+lFj|hR5%cHhGRI4*fPQ zS;8`s##rXb49m^iCi{8a3Gn>q9@6*w-|4iQ;BuPct~JKEdf(lmD+J& zt0}C^6y|3+z`#XeIL}Ufl*a=-{D!%_M`~Bw8lLkAm@UTl4ObIQ(tb<2OHkl<+)kdG zZGeB??{F@ntx1gSgSGK1UBpXG)yIe37%N-bUNZ6>o2<$*X}l2e$6juPr#?k~RL24( zb-g}*fM%d4>1zz>ecl^=+@QIHY20Yr(Q_^_82s;s+-8s|j{4(F%KaBVzYzC)gpFg7?I_lnXs&E-$1`%h#WYur!T6uDvOnuB=SKit-zu~^Rc7ZA?1H5XcIL4A0= zg~m2#V`(j2x@+rYx=coO`G?obBI!@)BqHeVwG_!mO!Q|v>+#Kcp!%qC>c#0kBJnBuGmXI}9nWhSk{)17S6er> zu62Y)Zn|iC$iW$zWmw}IBJ?~LK@a_<<%oX#TAqa6#8U^p>j+(U>Y`y^X3Q@#QIG!y z*o&gTeidLJ``-mS))JrfUOVtv-vqiZ4C^nsxT65~KRsdzor`$7HFpv2r*VXS@DSv! zfP2}ZlfE^u%K$qtO*bl5|BbYVU}>xtM)qNRI2#FnE3LJlPd!WTY{lkxDIdq-PNrwQ zKO6Wg-CSIyU8yIuh*4yk@*e_%a>ph?KeD)-zZnOlcal? zcw1Ax*985Q*P40|Z*Frl?gOR3@%@-H4sj(=INS={SnqR_Taoy;n()taJGvT0F~}ZP zq#ud&dD!Q$2lo`>ek(eo#B*b-p5IbO=oX?uo|6JL)^Y8kdg44T;P!iC`Q7NX@OusV z)%EaSM>-0|lN)Dl0XOM=_>L{q1Nr$$Z-aLuolC-djn~5Ob>1t#u=HAK*P@@Kd)x<+`*P$d zbxjvO2L>Gz=ATj4RHe=jFwSy%^Tu!)PtZB;%W~_VguRjmE8RWv-ISx(=QhB9*>s~m z50HDJbPt$U)twNL7{ui!F@q%UW0DZ z#=7ei?^ECK9fv4;D4jQ@_=pqleGT{4Ar5$Emlg+d4Embwi|+(Jx=-R`tX)9=KF0o&S?u`SShiIsd=wl7KE-tnb!tex5JMs+!j<<&?&a}kj=<+FYbXf)n^->Ev7jH)dOQ3 z?ij=!l#uJFZqmjma9~dJ?bpsy^eYj6H18=f;{Y%=pl{+_aNq0O8zS~Xpx?H%DFd9X zunCSfp?k4p`wRdLKu`0nTe=5I_blnAy(|6<9{LJkCg7C(w!pR?*VSgi}#vhpUZUG%Oc|>!EVb@wZ+2wQxR_u%G*Ho z!cLe2Ecu$C+Gc%?~@X|^uIuNjHedmN3aofUbdG-v}yM#wZ*Qr z*#N*djOW_zXy?|Bkuom!Bz<#&@*p?b{R!kKbwzo z?!)^kdG}ZU+NzH+UMr8z4a084Cq2tN^B(z;9uja26mXnr(`mU69@PSSFS5=(=Z(<+ zw19@Qx@eqJXxvKSGc&Z_&_aCZt9|MS#kye<=o~ca9Z`@&^vml=;$Cpt8)e?x0zJG^ zfOR_3L!{tMbI>&SWssf+v_*TI(!}?9KEo})-=#hwzJqt;8+MFCA=IxoUDit^-@%Rv z&Sxt)pRM40wu1B77r3`j$`{^Ou>OA-V`n#PxqKh?>BhtUA#AyzT|xiD=qwfO6O(oX z1{{ElTl>-o;2&dyTpOV?%(xr8oAy=F-i{=p-|ol|Yplb?+BEj8_^hGBO4Z_GLF25CQ09qO>vqxaXxu64&VRj2qn?}Il_@$;N37O?B+f6Yeu#G~LJU0_i^5bT7M$r2D<573?mS?%jaJDZc;y7Qx%( z`LG*)cSyfqNB>qwlOn-)TVKX+Yn>dal~wh7Hhw zf^!&39>zzU!+<^0WQEURV2&up$4K5zvM6XubyV*lVqLubuy5rX35z*Z7BL z-3U4H+JYCey5LrF#*``{rT)jTBfkm$PvBl^jNkQpXdYtmk^Brjw~cIF!Dh`dvWEwo zJ~n)}*WdU~UD^=-enwR+u#r6QSt@s;tEDBguya3^?OxWhAv0SU>W!Tbz2`LCZ9b-o z@42S4DT9x`NcrM?Nf+wLb7r)|1=rPOdun$?L~j%D44$(HJGFe49^-i~a65q72jAoH zJ&^c4zEdU6F~$dn$+oaNLVvxJ%7SeY?QX)jY^4i&_|6233zxC}_G8OI;3tOGvAGZB z;H`+h)V#SfscB!Qz4`6V#O6PDrZmNL(w*+u(-Q>mx5i$8HblL88#g7*&D#Zgov*@P zXB%u2xduY+Jk>g{@$_r>-iPnU=auT;56yc<|0bQl1?Q`>?lg{F30_i~3%-bNzQ2&h zRD8#iKYdR`y)&nE?sqPEV3KdJ`XY=LO!ECid2z0S`H(UtVXh~Bf^+GhNxsw{CD7yj zbIyxoBbsT#HG$jG>Du)Zr{{yMbgzMP*$K7=1Np{Ahy#^G(s@>Vv-N~rVVA7 z2p;aEz>{}Ky5ht7fcJUatpdCfUne=$Z$+Besci2NI4?k35KWT&K{|A{bp$t^7b=o& zSK46kPK2R8PG8}`XX(BWT0200>&Cc}V+zlp@RvmR02yvKg(pyWlL)s`IPQF}^V>S@ z3~$VU1jt1$DQERbw}c1Occga^WbuEo9Q2KtT8FwUW&C)MUsviupJVJn-!kAwG4Mlc zZN41fMfp)eean=D`d?2-m<(K^Zcmcj#Ot-Ze|Tu7|5~&W=E(JJ0}`}$LVatw477o7 z@iz&+yl)aRmthTJ8qUfrz4M?iX4XM2J13${7ibmjQr|K=q5d7c%#`pl6W`LyY&l+B z-+mhR<(O!r5BZdIo|>+X;A8qI>`V*{=}hwF1gm_p!78URV%6N#A5QX38<60OnU+8@ zi*MTSDqqa?RTQ6i5B4VV_)T)-dPis4`pY`g!KZSX26bkm?!&TOA<~CD3VMyy^>O*y z`9Xpq>qKV;w$j?@o7zg!8TEaV*GR@4>2%?)VytgDJ^tZzZw&nGP8WUCnipg`MF~-Q zmx41Sv7H$>&p~rfAgza^kg?nhqf=DgH>Z$GBzwfVCN&gZ|H;2ku7jPLs5G0x|{ zKf$^2vI)M$xTE?ub&MB$TF)PK@hT`omgAeYi0`9Dc~+Dc108srEb|$(^)9VUy{wjf zLFcC52c4V$5OhBOS+3{MB1)}FBWViw`v13VpgT6@AudVlEf6QIja#CkxIgx%S&yT`fGsImn0 zt-$r2Ig`8aUf7vVJk%RotPnj=Uu+uEnY|w2xsW$$tr+KBL;mxfY3O@7kmKTMF6jjP zkTDd@9TaDbeLUuZhyB0kO!v2SrV-t#jYxB%QzhDRqK+~y=1O1hL%+FreFNr0(7)2T zOq{0*(V2<@f{n@|xM{q`UdSBmgUay#xl{G~IQ^^hlN&WQ6s(fGj{EAM-yxl1DMBv;m1VMhSE2k;(Ve`A3fq4Q z%}G$FWXglm(%Efi?CIBmrvvcg^V|fZ=8wEGGTZ%1k9zyMd)H3vfo`;{fofoMM_&sIjP%r$F^x zN8=LOaYzB%=0hKd_dZxS=B1xhcN5*HI19GnhU#vScLCAWR_bqb7gLxF6HPw`9f~9L zqMP@Q(L9Og5}{cy`Gn2o=1pr@cc|A7c|<=O_N|=9VZVDW_Pe{S*k_G%tQ&BSbvMqj z9<}1khBX7WW9!)dF4hFd)}zo%#@)kb1ZbY=hE8G^>AbJpl9mJ=&4aiLGN2S?CgXg` z0-OhpEq>9L;vl&(jqpHi?~R%DBKSedILJSUYtOt9@nQ;S|2g7>PKr2%FZ#T9)iu11 zJC%m9F5#u??h1wM*Px7?_YwjVF>gK(9T#XftDVDR8unp+FoM4q;H*|W?^$G-EN-{d zYtZ=~jCEbS*B$U=B!gbPv0o(A7Y-zy6WN!?T$TDd?gp7CY)=v&T90qQoKALPd49b? z?1uzT+9~xa3D~1+<$XP?L#5Q7e!?I670z~IPKkZ)z%ll{;~WCcdIHDT_nwA*@7g&8 z!Mk>2KkQK}Y$;e181I-zO8V~-I))*$WL;QC~+-=<=r| zY;j~y1M%z{|014-v4PHXfX651)BaDQZ#rkdvgIcL6q$zy)|AH(7aKLjY^h z=u08OKdnm_5nZEgn=sZ94SO4}V?ES#=zv;E6**TH=cRpq<@$#=SQ8$`-v5WO_rKY4 z;q%k$abAGW46Oh?VotpV?YtD{6KE{=D#5DE$xs%gDs}Z;u(>|MQMVR6h|U;8KY+e# zVf_v2dy^v+x0cT+L+>Z>8QV&<4BX%@=R?Ij-vZ4@TplLc$~ua$KOB9L`6lBvE?>iI zmR;br{uhbGPrM0yhT-*lr>Orld;=O5bh&2?XlqiJZS|yf+v@9vf}Rrrr?NW%beY!h z2T9K@lAbpSJJz7Zq`(9vMZND=C$Wc;?{aX2{;=K=4E@r-%1r06;`|KuKn8FRu8Gcb zk|z?KpGc^Wm2^G~?x9TQBb&bj&%l_F`>>L->gmnG4%DmEr-QSAmxP88=o;{&Z!VB@ zofn|?U_F*KVKv%uHQKQO?bz2jW*956YiF5LthlTuAauM$FU(t08)1|dd=vMnhw;IP zF_U;7-2sI0yp6_4YC8=^@aaV2Q9`eB9`_BBt`>SD)X(3y9K-z&`!7gND5Lg8UU9JN zOXtJsUO#>Q5IJ{{X~vq;&|IgtG(yJ1oGj{|1JbMP61-O4Ym?{*4Vs90a(@C$Riqzt zgkmSww_^|AaE!0YmBFz;Bby6{<9#Hk$J#W`r^h${fn>7S z^ZsG1Lm^%l*L+^F1LipJypgcUtH3=n3}=A1k9AndyG-^_(EsVI6!BE#%lcWoGa8Pe zOwkucf=Bb6@~EFr$Y`M>Xh%iT+A%ZEdzF=Q`&h^RIba}K!Mcu@?pq3GK`+XEi*0Su zzIC*9KH(Pla?+UL2-zkIyjk}V-ZXsixiendkD+tLtdB#QY@#*l2V}2{_xytogLacq zS3A=o%HZ=o46xVP6FN1|e+@eLL4)HtD9d%3z$s`JuD%=w$HJ>zxYrlhQnCnF9Gn z!F=d0*#1${eb>!;k#rW|1^aVH19;%PNnhg~sE42NmduuXKPYM50-CqrjGYB% z>?}BAXTcde%Sf{6&u8mM#@GWH1GvQ4L-rcwIuP^N#s=7l#y;lw`d=JZh_BBK{%N&< zRm|z?HyQjNFr`s_Gwn*0#=*h|Wx*P@1#8$AoL{rpCC}3Nh`04dqO15dz_FM= zfS;6dKTE`1=Uv=;r}gO=oPCPMUj*LzqVW$w*F@u_KLnlAnCA!$cu)P4uqVrO3;iM8 z<3c(Ood;f+=D2Lo+{mWgpfP&7XnpS6TrCgKnpWon{aF*>`x|Hv37!4j30QfJ+q!~f zN&X%%l;H;M`Hat~clb;raCJ4xl(N)?_4C?XD+=uIMuFXEuV-<#vjubE)~(oM5hPr( z?4$K5E#Iho8{?67RtY=?d_-Am;@K+I6?_-?8+bqQ=jLCq{qqcxpP2s!*%mPFB% z{J=A4%`fnhr}`V}E5wU?%z1hl>k&5r^3FKIDdCIKqVM|AM>%hl!#3Z*&siR){trCk zyb0#SzYzOWXfBQLT<`^j^n!G6H}Vp4U@%1c3MkLCm+CPd{s9{oCn? zp+-y5=2wu9V_I-uWefIg(%w1JOPcwErf(z}f8MdiNi^2X3(-Cl3(lKhj0)g>gn-}D&G*O7OYpLPDnc)v|P@s`jg%*WC&2TI{Ran~N8`}0WmUn}NB*rVz~ z-zwRfBG!T5f6oy-^M&7sz7h;36A$oZ{ViclEans_hvH4Ee`NI|k_PZ6>YgOuSSB&@Jfa1q~i$?6XScCl*>#*OV3HvP`!95(0 zHM^B3!IN5G6X+S}k~f03UI6dgngw{p+;M9T#=GljOcQlfEOZ_bGy>dzdz55v(z($% zl9{@?J9Ak>H|D#_dLMMH6QR@bp+D?`E&Ueejj+*;yQBTQR(vO|S4~EGT7Pc(X~Q|v zRjM6Z{pwC(gB1G1iIWh=|8qU8N&R22HOl<{>*R@uPvuiM+d%9BoQuK#IsD8AlUl;k zZdG60x>1C6e?s#p&KGgG+}5pU)Q)X(?^O3&lU*|3ZLqP9{M2?D^S@4=DATDg!~Ub; zf7K)o%6*u#`9*driKW)E@F{8b39xwY zF~YMfN&)i75#@6pmrriTegZe{5g}Z)5U#fs8R4f+@i^HC86~Vf-FI?5$iE$PNyb}u zK9BqSefmzyPknWpQ`Qx0{HHchUTWtyC$|&QigaJCH>JzvGoeVgYUG1j_$gDk#RTU9 zs;9`~R6gY`=wRDYif_=uS7XVa{Xhd~E4~K+`<#Z#`uer}MO%I4lm6>W{tDy})ZuSC zISk*xQw!&**Z*%%QJ93Gox@tUZ58l+xrP1zW7~d|e}L!vjHfRj)ylvgh*74x9T9k= zHah9?-lv_B+jeZ#u~+NV1KZBXeCJA7&ygR6N&ksDEUnvP)Q;_mrm$pg8^A(wvq4`d z!-hUyKs=PjDc*Cob-TSO5o6e(H#tw#AG+`_c4mXcQ{L$7*^tjvq|3oWcO>u~U}`ID zfpguyc!+5R``5@VaQh{fEnwcBCd)tV2>s=LoG&|#JPW8DC)%MWLU}OGE6S(#1Uxcd z&8`Y)b-RkXiF<*$%(MBXde28#xq;uasalw5o9(clvi%W}=h@4dAM9Hb$6;7kRjq*;-<@qneb*hltwmo!O{nhpsDwAya;?DGk^!^3j zrT$KYVLu?#poDXy+HRM9>o@R+m9P~`@7cnVE1SHNwuSm?fuF& z(rA~$y44PxdDYwF%uwU|FGHz~1&zHN4>~<(^xwa^jqg9h_B3qaFg$<$#DL+?hYcR{ z=Xa^?WSrenM%zkr$^gdw0LJ~*8249W++Urm(A{?4)fo4&SFCY0#{Jb8_pw*3344?t zX~4MOfN>u>nHI>O&p_VY4z9HY?rMY^(*~ejO|B*Rd8rA6*1}w3B3nhQGjm6U{f9 zAS05V>Ja9i-(nvp-7`%0SmUl?n!5pS){rdNvN2z@q` z#(&yhi9TIRvX%Oqmy<-;7d9F*1>Q|}q;R?~$|m{sFt+8yeP4tXlFT4^0^gOeYET2i z1fDs1QkNF?GT-0B@~cR973pMUdE$-*l0!J`^x4UJc`v8&ov46Sh8>=)m-liG->qtd zwTb**E@s|s__s>`QkHcL|A(YMulu1+ep$u}>EFmWYKM(}0oUEqpZA<1zUI%oS8aXy zNg3ZRKa0$JZ+IS`pHR2Gd?do}0~zm~Xdh|z@E#&=*T2S6`;a@k9dj7rcMrD_t+~+{ zB>e8?wqQT4?f+V+0;dsa$1z^R(Og7WM>;9UOCOoiEH~xvra06_j?gD_1+TR_1+TTjKDsq-HF)A`@Wj>NiL1dASA!?6 z22aF#2KME`4l8&f)-y7&cBf+P4*PPg*q3X~!`dD87v2o_Lxc z(4J7zFB|;v7~gr(;8kMg{R#Urf`6Tr3AxW3(@kf_RH_@@(dLK#B!K-d0qlPX(Eb;M z(>c`j*I|B!HH!69G4E}}en@}leZs43w?j0p&il+hUg)$xyPw`Pwqfl&SB^gy+=mIh zS3B$XauwJ&#$Nvb_WEzYUVq4%m}_Q3#>wM4u0Byyi`v zd6{-4p7u{RJ0M#re5Rl5Ta(=^vS}EDeMx6zJ@Z(1i#lN3OvAXDj&U;s<0fqEhTSzO z+Onq}Y9-eZ_J>ISMBiDPb~J|5_#Y>d4I=K>T-P1P4ch#(uv3TjbcFu+Rv7M47T}0H z3w3~TZUJ7B``&BqeeAlrK%J82e++fo41CZyeCM1x&`W&aZqO3OS6VaWH4u!|xZ6F> zH*9L1{}bo?;Z zgK)1km(O=PQhdNzWs0*6agrkAP&nqUER#Ay$JYz}*v>}AH}qAa9d>Ub+V^YvZ_q=3 z_Nb%JR!RD)0{zsYkJX{?deL|N=v$5GyKB&Q*P-t|!g8IXGu}6RD)tRtS4VE|#vAK= zs-Pn}+v0z);oOE~<=G9n%JbSi%yfr0`p%PL&Efnk^y&H3*OC8xYKP_r&?l+CV@-nl zJkMMIMEm)99~#;#9d|C$94Q8Kq&V-sv10&J0-kud6UmKww_uFIU4XzJ)~k`G*!k<2 zY~Qq-6KKz4wqj8bH^v(~YYg#C%Ew3FZuEm8c%$#sr?NYd+{o`S_$5(%wFCRQhI5`p z&i0sWuW~bNMklHhT?05z+!sD3Ge_oGh;QUs{|?@i=RS5P`W);|s*kmBe$Ka%&u2G_ zyE9R5)PE%Hz0-Ie`o4wNmVkHWN09f?p0$wY>l)BL;7fk+rAF|BHNfpU$n#Bdj1l}G z7yQv3-6kTp<1+AI=#sq;O8Fe?LsXvgQ{3@>8DwGaD3ih-_wSU*=xahmVQAc;K@;Qlf zm_xt@Eb&!m%kiN1ZRnmopvls^c;4V0G_a2NQ@w}AfNwql4E-3l`nSi4`T8c{jqH1p z?#d7PhyI&o51!8*DWf=SgA@BXn2(`5~9 z#7~y-4@Jb^CgH$*e`gow`+E%-k7@cS3WJ^B*Uy>4Ofqrj8+D7)fIN5)E5S_g(|!ch2V({H=0%)o zFxL}v53Hf_zFfJ#mhNSWtmgu`$JSKOovDuC;llpzv86sq<#0VQ&Ql+0S*zgu|A!m6 zKFl+I{|W68=K3J6X;1EVU7w{r>$BrdNAOU;?ElGj>#aVbeMEh({%@*JZO{6=yw(x? z{l(ZnOC(seJ=+^FZ|cAOFu8WTA>2kb&1=JG%dmxK?nCP$ZQ(gW+uwBr51!)nVd_Jh zE@+>>h+%g_UZlO|pdGfaOnqtuXd8XX5jwy&r{_IGwgP_tlty#v2GSLLxHEb?$#q=R z3v+wS!_4-mWu4v8?SuDH_lWz>UVBp3UB7q55!#0J?+?DXh`LwxsQWU=*I{-4Z9c`( zar2-N&i5FAR_B!xUJl+*yqo!Ms~D%rraSO+XP@{14tlrS{gs?I;|_q`xC7v54EA=# zjO+zJk+$(RO8n@y@f@M8zjOrOfA1pj)6xS!n~nMl+W5^VGjAdq!Jcs|@hC^=1Gaxj z-;!1`A=mK!E$kzRk-R#A%fLKC@&;*3;oYxsACcS}@a}HxX^3$IKbp>Qu^+f6p95Zq zZ*PEodf*E7=&^q+M((BhPUvlGPkQ^6+Y$U-;3DvO;KKOa{{h9(>CHrsgjd3^!0r22 z*MIbPmaS>d>j-u(mwQ?yKJ|N^7C@haeadVvDUr^Idj}T2h<%4R?{pk@4Pd{MMz_yN zy5)ZT!C9{dXEE&8)OnSHV%mE|a3LSnH)){S{0_#=$>wpUKX&N*u}_BdD$wWgUh&{Z z!?IksW6T1ZPv}duho%19x4i##-3ZJxc~48Io9WAsedxiDEfNQb(r*H2=9Jvqndr+- z#G0WvYgB)J8r`QLbWSIBG}4|6V-4`NcE)Mw0PkbhbPj@s-}lJ;7Wkirj>iumnGJ2kwR}NPDcLU5VG;Cs|m`TYfnVaKv*NkS!gd-=5dX!}k|r zUfbV2G2cpA%yizNf3lc%Cy_};dFg&f@Ib%rKau@*Da&HOfmt4Ngnn&fJOqdrVxO+O zuS%Qy894fFrVPVgBi@@DZ^&xDrG2JRWVPt$C>}}fWlW8ZiwM5?x@M=}#5ezAr6c&; z$1g%ItqS}YeS_{XAlcHRSji?o-33Eq2FnS<@%f*X5ai9F;Th{A| zd0ppKS+xI@^ajAOBeZu5;iUO5k@9Ol#@$F+qkniwjI^0dXQmv%-vllKFSUdhs%&ntTXTTqcfg#mIpBQa*m^yehXa+&QOT?&oCjA ziazkxCe~~4{5uq&IMi>L|4=;iHJ&dAnD->>dkg!LNdrCatLa7FqIq6{F`s?CNXiE$ z9=bW#5q!rj<%8O2vN&+DfaNE*Uhob5Z9_tQ9Hu7^w3!!(X;8tVw|oAr;>Lz|lr{8T5Rap*y@r-$nC?Zp2L_0Z<~ zrh07jID&iE{v-8>-X72)ay`CT@xP%S+C1M>kLNZxf^YBsN9qy1J$89TJ-*)3TRk#! zLTpPTfHl|5)XqHbki?u^%-3;l-0E$B{fQwstFGATY&Xk8v|a((73U8JK8x`(2J12w z6|#aKV?Y|l0vcE7tauvsdPB}k@#RdY^A5s!fqitAI=z_AQu~wwtW)4D^$l##BT?oL zdlzKGiOLT>M(ew@HjXvkjp7_qsF7^G(wWos`T8B@tZVI$o|W&Lp)~;PYa$&Z=^wGL z-BzEa93b9Bb2CCjhj$?&mPr=s2D%izp!}`{+ zcAS?CJx1~f+DWXx^k45OaDX)$tox-v_nC&VFQXUTXQYhj?I}yOUhN3JHSQv0sjeO} z=1+RcQFJc_+4rKgD{a2bGUNstSI+yuAG1MM7SMu1^Bd4xyc1j8$u>IXhTXK5t>(mp$3a5AJd)OA16B zr5*O8VOuEmNtcoa`^H>Ox{>aOzj7%*n2U5M^X7kdDewIc5oaLI=v$9uE5Cf#rA!|s z^Qx8UGP0F>zjY~pNEH6oQt1yke)5D%x$#q?`)sAr1+%B$;yXQC`THi9(l|oK&oJV@ zz0IZkZX4pnWh-ZMUCPEf8D|~JXW5O`h%-~s?vOKRO<%0>y#5mLB1fp*ZLHJao+7N# z@cvs4Yg=ww=fgT#+YYtkgBPfOinM#Rbv_Ei8rs3Frm%g++FKjWX#C!53fp1|JEwLW z$}xqlH^N>^P&*E1o5FZcB-RyC-fJlc>o$dH`|&6&L+$7+GKKMeJee*}?Kr}F!C*mzIb0pDX?K{YKJX>^*FK{d7e9Q8K=cGa3JK;oq)= z$A3%0*&ZL^|B;MukMMs>`lm(sb6cye?JAY0g*ifRJ!*Wv{k0+E?`;cTgKm3>=cs}n zG3_+^Q_gA&+ns5Sm=B^a94B5Eo$lN7L|e6as2mA%5z{=aopL#^tl)Wu-ezs7ymqR) zcYV!kq8xYEDdwv=n5(YkvxIUV9PT{h@V{&!oig}knur$)HE+WFwVu{va98pO?B|1k z&ta*dbJRx-ymTBj@bY$RI9_(G(98AoogeVwXL+_!hiT|V!-TpJT#nGI=b0aYr;uAM zX`e5~)F;o<7)$dq_?1e(qmE#k1!F=#_HFcQK1TL|Ok-rbUyhL``#?`FcLaAm^j{n! z(c(pj^L|r z^;h2N-x{&hUqsU(0LCnTC`9@Ahhv;4Td5;(=Qi}%z`1EnZ}*y>>*7Dh{P)$N{e>0u zGe5d6b}Q|-3}l^Hl$7;4*{S2Z6k@z1j?lV525FYMCb+ynNu;vB>VoP*ena}YOUAhIx2l;Fva%;mnw*n6 zWolmjZMPQ`PIDAZpE0v|*6caXxp&N)f9H?xT5$J|7rNYwN=nNXFInpO$+Gh06_r)@ zRM*t5xc9!gl|TKN*S88S+4rwy!@obRv?|Xjo1WkN!j>2R{^r|r=YyfXOaHHg?rJlqdUm7PWqiLzpIdhr9+$o@ zh=FG=7~|q2*aEj5u?22Fa`7p@n-sP{!T)Pze>XL_l*=Uy{C^h%HvioDc#h#YZu8#} zXY>2KcwWGB#O7b6;2GIl?GRRg=P^9(Hh;Yp4{h_0`m_1{Rd{yU`~l<{$iq_}H6lE1 z{{Qg^9+dxoC*kqq!FN-(&A-0O=6@LPhnw(p+x*SNcwVA>YyqeoqWt+RvQE7I-?{?AE@iB!oe#`}ZnaV8$WxxA`9-QA!y=-+`xN=sWTU z@s8?tCeokWRuOhAS{PKpl-4`4b&lYGkN7uh4ET?r3(}#rReUq2|>Bkpf*`<4!KKcQR-4tE_6tJ{L zZ$CX&&kt%x)GwVL3Z-{s+k&U8k@0d6o+IPs^bxNJ@rq=;qA2mI;+H9QEgW&t=Q&^M zVuU)X4q%z%N4yc@yOr|nE#5}N8{V&YS1H%ac*XRVzld^YR1wTtp!SZe2l>Z;$N5p7 zw!pL8S5W_Ma%(@)#?Pi`Zu48v+p|e#KkZxat!JashTvPR=P0f%;B42@u$%o_Pn!L- zZ^5@(k7#c5`!YDtR(hW`hsB7nsI(s|!X7in*S-gfFt6q|zx^Vt-0Y`)_h>{dK)!+N z9(`2exd)6A$InD$p-B9$i}V+`eYQ5zUyKLOE{OCOIDIxR(!Z}d*aFWLM8+5JKi7j! z1pLqSpaTj2xyXEi@Bn^}NBUm?o{f?5B|MKr`b&8Hk^Tan=X$iKz~^&3rkK<84bR2| zEv_wahfY5dCLMRSz`SfNo`fr`?`dHYw$qv$>2x}m@O5cn=C^3`=X%f@#qr}oJMN(G z$X{P|qqw%fM!gPNT2Z%+IhtF0i+XL$(A?Ua2m<+}Xm0Io@5R3_n2?W-V=W&E&r;2; zy(K(O&8@vJkbe(6$^4(u(ra&-f0O3c-WSNfON*zyW&V0QYyN%bvq|qyw!ob_ZHc@# zoz(I`n4YhIcheCg>_=(Zx1hUCdR$xJN9(jOL3f+BYHst}4~H$V=}GcK+l0|{U+|0g z&(EiK-<_Fvr)v{rIp2p4XgV?|#&wF)V>} z`0+-b<9L1Y>M^TP*lcJ&B=M_+K-0=xaTK;8ko>uiBhd+>&S>-rb)UTO>c z5Pf#H(-ug;XA6u) zUhSuCfsA-tU{@{P>)`GZ?_E1=fpJG{ft|-~f$`7a4gXuq5f5dm$h-ZJEihph-Un=f z>^!{p+5!`c@NUPu81JokJMl)^sYuuUB`$YkM4U5WI*O%0n;J4(n zPuqn@Vq$0ZXW5-HzQ4Weba$}(bXU8dg9i+{V)&%sq~TW#qV9(uz)ws}T%`f5P;vO- zEyC+NJ3D`NE&bT-?Qp5(9UbLrT!&Xg;J<`2;nee!_!MpwA>pSl{EPwtLR>IThH@V1 zuAnR3l)2L0-Y#=z-<0xTxrsBxtE$(l6^{sLJg;grpE)CZqiwQLz9Qj4RY!)$C`a!6 zkauFDx8sd=@1Q{sba=HIywMStnC|L$KqOPk%hh|2puKSOE`Del7k_Af5SM?6l3%4K z#_=!FsNv%5P`1Q2rvi4gvb0#yL~C>VmriKS>Tjq!)D-@x2se3a9T? zNFP@x0T(S{fUmhV{4jXH8V$|j2goJxB3F8WE{x)2Rk01#(P7fziiQ6(y>ic{J_Dg)Fho>WsB|;hb^M` zQESS0JzvCaK^#2->f*e5e^t6%F2Xj5K#%9`00C(DOF~KIh%Wm#Me=r_6X@aNZ%(fx zn00zq?xpDay>ZOKk$?HUl)uC;NK-Yp|DZw273dE50WZiL@dW|M_#!e=X!uZ+lR+T( zpi%E5l)c8U89r(Rqdp?stCN5RpVp<1+`HJI4^9sX(9*}Jr=O$hjZZ>|_;K}2_@L5s z{(>li0A%}`zyqs#Sy_rcUC(+D{ZtVH78^irx1f5#FZ1 z+{3l(6r(?j6#H=_J^uv12JMBlClV`R^nv(hH@HohTLoV=hZ7ur+}AQNYW3(Yq$lxhC97(e;7U~oYAY%2hvk)V*14LJ5XEk6Zv<@P^~-~ zaJl!%0YNPibbjSp*cCCKwPh)7i9s?2! zb${V@buC(44j_(zD^7x!bT9tR&nJs0JhZV8qh~O_{80IL-K8jSl^+uBtMbDC&3!)n z-$(a_{{!Np{kp?EyAyTyc=7vEzBMRV;>28J# z`I~A_pE`UJ?h#tJbVp8yLegJ*jnF=1Iz7IYUJK{?QzbB`M zhkq3@JqsycMWol`bNY}GpW}UH#AkRS!^e-;;n&h@@JqNtVdae2#Xpk&@so}Yurzc?eL#WmiR=zZ{z8$&@Qd-aos-;qL|~U4$|`Vh{J^w? zTN6Jud7RuGRNP-h_;5%plQ@NNaMZg`!>QNix31Uput) z=q%#D^pMjFEk`Ln>pTn`5;cy~+*e#n9JR;KjDSSM72H^q049n5;>YYzej6{zymb#F z^_48%oh&cU7WFA-%F-iZIFC!bSp!{ouM$5a&ZVzQ7`TLiOBlF>flC;;gn>&KxP*aA z7`TLiOBlF>flC;;gn>&KxP*aA7`TLiOBne7AqH%LHP|<`#_tz(ciRF-pa-{LZ-52s zWdpy&b8qaB*db&~!4`ORzK)_>7C*ips|cDNzPNa*eP&fzg}uOCvh0WR+|_0FDTOoV z*cVq;+wUn`zQTTQS#^!4vcjG|=9a<8WNKyA%4*M&rM32()6;JmjXxRoX_X~qk}swomSQPK`6z$bO{{JpEV^1ia_;;Cs%$|}mLJtd0fzWo+Osj00lFT+aaq7{o5 zmsPX7WI1XA|8#;K@3Hb-K>=`=RIP+D*qU0Urn-dOr7J}IlBFWOvb=0L$H9Af<-KJ} zDRQX619weXEx);p$`!RJmdjSMD^}1tp#BR5A1eJn@G0m&Ob?z81=lGTe*TZFXC&^a z9%^{qA8ha2z3zQec#8O5S7rFE+X&jJt;8x({_NQ^XHT%tt#B_YFSFNH+RH25rS_7_ zip8EKE2`bK)D0F_S1z~DxMOzi^fC6_MU~aHo{A-7#*87VS4Pz+%9ItJ@>1#>8Kcv0 z#eaLcI$_+n31d~n7*#V^nO?TMvU;Vx#`Dv%3HDK?_UTi`*auIktfYKI=A~u#dP>Ud zqe?hW`m+eZcHxaQRqQWey{&RZMX9}_(#~fJj>ln$`IYwa~mTsxMpFAyJTtE!m1Uu3prf2rIub| znvzlCAC9W|p*>~B+@hjX#xv3{DbrI%q;;ZdsAM(zS9J{+>;^BZ7!4qSTdKIoG-XsN z<;J+w%AH%WtfKP13cIYYz!{a!#fHZ%G(aORvY44Bswt!21muL}ecK#>QET^fITe#Dd3aKh>7Sm=e(E7h9Ndeb?T9>V$noO zgoeO-utM<{!9lGVHNN1=jOd!Bl`Aj^E-C{XmYs=diSwWsGLs%Cyq$? z0ealE3khsAb+opaKfOqdZ4)roVQy97UJkK{NwuWB5}eNPpo*52FCHz1_$W9u^9KV{ zB03WHz`3dH6_Q2X1~GN1y{4qvQ&kHBC&7h8(Vl5%mtj!mLQKp&oNx3f&q%{4(qoI^ zqh}dW;Hz~n5!i_alOzq?~2cuw0BYaRTRmu$JCW9*1ysI zJ@M2dKSHnIVFGUct||vBDO|Cj+mzOoEynJzyYVv$%B5O#s84#txIDo=XGKkwr-Yd-#S#R~!*f|J zlo`|mP+~es?{X}kU^gQ21j)VxMIy4jb}9H5S4=M^JpJWj1}4~r9tZQGDj|?@fDj!F zNFnVRbzFqH841mJDZwO=Fe37}qtb&>MSR}|2CaSTX&0hU8D6YS1Q$-%{i-m5CHa=4 z$#{9y9!zNn4Mz?M4W}W&fLg!iX<6Ay07{(-`N{Y*pt>LgaOF&i32ZHnCM_*5!>pKLrurg=x&Bp=l}ET8 zKkg&4V~J@xIi#c}`x=!M3jQWB6nwWEZ!4a7a_caPTtp&LKyt6t(a5ldg1>9T^BA5N z@a)BNJQRE%W5D~5^zx+S^JIyb2np(}IN*9MSfEMI!Z7S|0~d=+sclN2H(3P54@Ulp z_Ia}lo%su=PS0aFB+QZVXd>8GI8-LJD`<2vrH5a2EmOh-`+e0Olm?~DayRBQ8@t`H_E06~Z z#gxHH0|yvW3iI;qrNqlvZH9TsTfd2W8N)F?)&!GiAzzI!)L( z#$3_v%%9_22wvqxCb@ZcM$3eBgtE;3rpX|sT3DLG8MEdV&W@IUhAID<73C}KqL8V1 zKtPS1H2)avN@wOb^UQ)bHIO9xh5)t1%z9*fHV;w3$(tplscSTJ(u_%rCq7)%cO`Jr2h&kBl zSzd-k4!gUgq)cclil-LZ7gc*omw?$UUSfBbmZGN zxba<8;-P1>=m?MvbBl}8=2m!SP<(_lyhcw^JXi>-@GJt899>&E+7y7eHD${^qajgN z)IeULX(WOpV^zCL%I*VNwem_ZCJ|k0?iq8Z%$=jVAa_ljKD98{@Q9M7GJUEMAs-7m zT5QuN@+q`0t%T4j3mQ81E4Z0hJ_DIx``ST<@Vyj zDO#I=u_{`A%c&r|pR_hfN2vZbl?*DyT{$t|I^<6$JSNecN~A5*fb$YFQw${HC1A&WAF2Qp6A?qd>xR{nstA?QQ@3>o^#K6&g(qCpXa*SFNN}Z;B^0>P0sfp z>nUVI73Ud2O2oy1!LFX(6V?>SUVr9!vm2TIK7J5TRawY7v)Y6j8&GR6T-qv)nbk`9 zbgv4lzFw{Hh#6L8k$QCcmNKFuGh~soF}H0UJNH-xHKaL=rm+|P*50xHcJ-6me?08( zY0-W~{|@VK!arbtV_f_FO=J6(YI`W0v(L`op?~#vzV^3jtMAy~o<7*D{pN7a1BaT% zo}Uc+fAT}^e-QTn^xN9^zc6kZJ7nj)6^0_pB?F{7$Au8>uC>+dLU7HQNN>)hg=vnzI zQ#`u*^0cm)cUP%e>fU{|+3f3_v|Sk%5hU3t+8Q{UU!QqwcGKL(O03cEVoFW7Grsr{ zT|2e4tKCSazc>E5rm+`S$A6W6Ueqc<|98t9w4K*f`AeTxvURV$L;L4y^>Tahbg66L zXrG1qc6;W427Z$sg~a(Uy{oVQ%Ie`%C?0cL!@{DFrNR_l?X)m(Yx8#ZTpv5t)!7OS z@n}*pmpNHuPU?HB)3tNoUO#ZEvG>{G;gqzq-m<0~#)_1N;yY0}8y0nGqASyC4{`Hz zi1wd!ZHnTr>8u&EW0^07vuf9~*oIV5ce(I!O_;Q}$~9|Wj5oF!2#s1FS7qRb5p0}f zi{C2;HH|@7M@W$iwwY0-5TC5v@I5wU(Vf`XMVR&1;6?RWGkbpNnZ5J)-ex>_?TQ+M z^OH)ow^h5w^=|92qLxI|9?8Z%YR5tfv11)t@L`2-?Yed}wC9v>wZ6fR0#)N=%W1Y~ zHm7$;6LJGK8?O|qimX@5&@^q8OXA4j*3QAcPCqHDu|~Ds?3!@|#)Z4v6mu~hcT$z$ zSD3_8)S%GdTz9e6`aHUJb?Vg0g4o4(n$Pf)%<0K~Hg?mR;gDCp)K@O+z5{M|S7G1I z{aeFIT&>?Ns95VOTi-XtLp@r>BaM@0F`SL_+eoSPOVqTrrF`}4hqY4J>hQQuSm)H% z4Byd~zbm<;t*tHR=VWqQW6!@ex3jmPNyAbpx6c+Amvj3xKs|8MMxfNU_T7ubroY^J zHO5y(iA2keORC6L*+fkIp!xN}@#M%r@u8t&Z{f7smpxjOSXTR8^X_WBYSi(#Do?Ba zT%mu+Z$nua+VXm@*7b8+^qd+Ob$iqxRlDcJDOu_iP1SON8*)`Siwq3v8-8S0$fYOQr3;!VT4xUy4|X0TL@s}uDXT#j^= z%9cnp?p;a@UdJ@vKcu;W)Bdxoa_OBb@%&W)=foxN}kAFB3HJWgsEl&-hx!PA4L>_4}L zyY!cfL*0GJF?*3|liA|z`z6{IzozNlL?L!e%S3&H+r~ESv*zlOlQ~-g~0>QM%JVvkU*#-)FruJcL~@eb?$@`tMrWjjz?xbQp8KT8*%7*e`U7tNAn+ z6P7)k)Y{&@fly||vdotsw*1O|&tM@1jUATNEYc9SPY3q=dQ_#g;lz@il^?5oKWt#A ze=sd=)NZ!1e_M~)f4xsnKELUEx|&us6uZ;%z|y}>{o3=bT~m&2K-u;7cih*}dbdsJ zs?64Z{nmyVoX@A)+8mdCE^FDJb-K0H2!3dH4ut50!FL-Z(m&a8i2AXLQ2zMKxMI0r z!xv#ZqgeLs9$|aR^RypYzY6PLiv2&}(6t3?-nEC!)wr}@IO2wmHGW78& z+AlAv_g$aazuWdL>DWP=4^Ro<+jfb4&_C(8QuTN|aI&W>DGYUoxW}zJoNi#S;P!m6 zQ$>jC(KtO~*NMlhD6#!8Y}OgXj}=S(OBVL@D$SNki7ohD@};|$#LsuGU*gNsa@UdK zl9HA9es4**X1q>#W4f*%El`?^E9k28N84)D+miSg z@9MEMU1aZL3vBI#w0z2jb)V?!^o^vtYujb@95;w zuFh^PiMGl3K~-z&saB6`K~!nR@nc16J6PQN{RK|-bo;HEUjC;5HrLTpwkB!M39at4 zhFQ_pH&}TXt1D+WQ<+!2ncXD&xzJbY8@NUHi2Wj)Yf0xieDP$Fw@!e4(6zPdu4wI! za_N*3++e3Nv8|*o6;Jx+la6<4nyK4fy$fNxe2|^5DFr=E_-;YD+>Y5qdZ#jiC1P#V z#R$iT`mN4RL*o7VL!S5d*1rF8yk7sQ?hq%vU^({}Rg7p`IHu~~?rFz-^D^xFjG*xY zYq`cIls`vFPmLF0S{bG9#Ls@eSDDBH?YJJ@@4B^VgG}eIDf=X^tvWDjrs?J6y40WW zQ(<~3$Kx78eczVU##G|3Ju^Of%RauoX&0hsFMhWs&-&sL;aa|{t^3w@tk|^grpeRx zeHPO;Es8_@l@B9DuH?;b_Z(y_LVAK5v;<2y9?fr4PBW}N_MwXS#>G>T!!^P5mYo3H_?biy)bpL=_ zLFswh)M7pD*2czg92fBA;r_5X)GrL(stld89_oF24&-+3?%1_`_xAe^Y~N;&r)N8% zETM%Q8ahz2)#rzXdQ{r$9_h}E6BI{ZS7_n0CFbIANYj@0tm3jkLxWOX>|sMa78>aa zR+*&ycf!BOwC!%wYQBg_6G8QW&d(;4G|^QPqQcVznoYPfuj3Pu%?~Mxx_`_NK7;7{ zYSj8Xsps~)`wnd0uN0$d!`AQ&cG*ku$9%)L^GH$2LWi=)Y!X~r@t73~R-bihh_18W zej(XuJq3Ral?1(moi>yoKC3}lINn(tE~tQuWAX9+S^=b)%uc-%{Z_4dZJ&Z?2Ke)1 zfu-CYy91fHD5Kc~m5tyJT05uKl?tE3BGT$ulttLj4d{u~N3wRFem&xgVJjo`lP>+J z=A=3*@#wMQuzuB4&??JPwcNCYJr?H&Rf1_uD!q)UsC}gP`0293>4N62eaB9(Ahhqo zuRo5cE90L_FI6Q?uQF3-+V)hQ%ayf4&fbC=bXt9FYfjT6dPdFBSX{!_tS(3wX{enR z9=4(ye>bcc0HJA%}o0c!PckH=8ynV{$nt zmF*Jm6gud&s9D}uc1vp6%_@e(77WB}=CfD!fSx0bZYFE_duOthl|e~JZ|W_@=Z{hF zfBZXrO_|q|j)A27>hEj(R&tqFkfi>nGXI$E-tD^&cG|DHwIA!P`!zvuH2jV=vlQF^ zD&Xqp3=Rwx{BrHsxlR`q#_Ppjfu&chp1pP7R)1!0Ls*Su$tjIP-FH-b=~Qcv#cS5q zn+r@sX)1~b)iAUCTl*ERUC@?^+I8*M8n)fNd23snwjFyqYS%j6drEWeHe8jxQf=_e zzNn#Q|3CZny3G#Te{GsL4odsIcrY9eA+<5;J;8fBqG>;QUYAV%=xy$mq?(V_(p@D_!HrLf0{} z;--f-pK;qZ=-wMDO=t37f934xYyUNzzofq}UiiBwc1_%IrhWSN-fo}zqhGeJaBkC> zTQ>Uo{EK#twp(4}7B@Y4PWxk{I$w`^c9HgdSU9dYEwwm}D-Pp|gW}d48uN=>>4&#rZ4+*)td`(l%MV|zxCcvPUCVK zm(#eM#^p3FC%LxBwNJE-h2gN)|8!*X&l@q{f2x*$e)r$or|$aix#WAL@5P}Ei1C_R88Daf$>Q2r7uTP~ zxHe|unkcTjKVe)OK0$dk*SKC+7uOGCT(7Ie^>@bFr|x{}|3O^mDXy8a|JCLg*Lk(L z-uO=Y)E&Q?OI)vkrIqp7__f6NWy<&)?^gT{{+8m`F!No%x+%u5q2|~8t@f#PFU=)> z%0sKI?#v&)LFI|+8P!{rZ@9+x=}%wzjpVJ5u17QFz^f0;F7Izp{lE5?b1Coj3}>w# zYr8GfpB2@YR^PU235L~Y@;bJ8%(dvVrM*MiU#$HGeQ%St_P%#$+o;d$v|XUjd24gD zx<9-@=jK}7sutC&%M`ACXL(IwzAW=~t?KeC3R@iN^;j0^zP^kM_31~oM`q{mt9x0z zGwqJQUlzSGdFInkwNKst%3QoG&nUi=X}iR~_Z52YdjIjc9@BHL*S^`9ojtFmyKZeQ zE|2N^XSLs?{ffd5=(8DKuh0GQd~@8TV+(Do@Wa|)q+^2@&$MmT@g{9oYdcTd<=Wb_EDiS4SK_nf{IjXbaC5hdqGP8~7(^##JyWBGST`m4q`&9CoxxTCLo~muLxu>Ps?QW~r z>dLpv`Pt>$;)Cr|twVDuKdycGdwIv~_$_*=ed@M%u6g{F7vuYWAiVEI8|&V;^$|C(U69rr)>ql^r1j^1@J#-~dmoHE-O@4o*FPUt ze`ve!pD90{e^&W%G`3|`*ZBOXYx%NLTlGDBe^UL7rQ>=w^)r@d`j(;pR^L~^Je?>y5iWMg}!au@%KsxzubIJzQHXRS+w`|v5j^w*Kkf--7EBSKCVx* z`J?-Y)@L4n_D9Xu7qfDx@}2QX|NNKKC)NG(7cM{HpMQGI-VK+U&e-|+iT6HeyY&ap zjJ&?CW5a}N$WKg9kBr;qxE7IMS{3t?TD6eE-96?6$9{U(syGDzEDu zUAX)~=KD9=aeI#Zh1Xnu;vW{+cYOHKAE|#iRm_ApEBxuY@a>uK<@t%%C+ou3WWrnW z6aRFeF1#rdo>%yfXNF&SKNG$~;dR%)@>(YRaDL*AXX?IxAroH8PrO-o|0|DV!bkEG z|LnbM&wr(u34cuCPu5+3dnWwJ{KUU(staF}3IA?>;;qKI@TN@o<^06k>t}{fzMlzy zH$U;OZ`FmrmI?o9e&XLMb>SB>;UDBDeweEZe71-=U?3AT=&L`b6tN?%o>)cmyx9o5Yk6+s-;p(4MpnZC(>3;y! Cm>IJG literal 0 HcmV?d00001 diff --git a/tools/ioemu/pc-bios/proll.bin b/tools/ioemu/pc-bios/proll.bin new file mode 100644 index 0000000000000000000000000000000000000000..0489cc245fc524bb89eb36582304617ec4ca5b59 GIT binary patch literal 56856 zcmeIbe|%Keb?Ce2%+Y8h1{jF}51`X5{@bstCQhanb{ zB7}o;d2sk)LLI+kkTIc-uQLc0b6vlCWlBU)`&=n}s+Z6_*^k~X(*YSVoDQr}c@ ziA@Y<-goVDMhwR|%}e{a_x&;Yd=6)?z1LoQ?X}ikd+i@*h&pCvKq*yx4zE(`g*8e= z9rMxu5VZnPCwQ?~CU4*iK6s)OE~&5cOW<*@{`pdT=;ce{68ztweQEDpX*uv2ADr{S z-}k|<`rt7iob|!4_~4U1_=FE0^}#Rs;A1{`#0O`5@N+)+kPklKgVR3vDIdJg2k-I0 zjt}1EgSYzNK_A@jgL{1N1|Qt%gY8oIs{Vt2>goTX(sJ~_)(5Zg!K;1nDj&Sk2d8{+ zs}El8gIj!X(g!#D;3gm3=z}dET<3%1J~-xsqdqv|gTp@9^ug*{*tqP2FZ$pMK6t_h zzv+YD@WJPOaNY<1$OoVE!DoDM&Ifi`{1X1@ID{B#|Jw;c$*L2>VpS;aK8`k@xdE>aHkKpeelCR_#q#> z)(5Zg!K;1nDj&Sk2d8{+s}El8gIj!X(g!#D;3gm3=z}dET<3%1J~-xsqdqv|gTp@9 z^ug*{IB?kqU-ZEjeDH)1e$xlP;e*fn;Jgq1kq(6 zT zxXuU1eQ?YNM}2U_2Zw#I>4Vj^u)6GnFZ$pMK6t_hzv+YD@WJPOaNY<1$OoVE!DoDM z&Ifi`{1X1@ID{B z#|Jw;c$*L2>VpS;aK8`k@xdE>aHkKpeelCR_#q#>)(5Zg!K;1nDj&Sk2d8{+s}El8 zgIj!X(g!#D;3gm3=z}dET<3%1J~-xsqdqv|gTp@9EQP1UEaS$cSY;fcbt^7yU8}c zleS4ZJVyG7WX61=DHDFx*`xNVj?1T=G4-Wn-uzNiKK!K0=Y)q{QKf2>3Okupc#flV zAF`P{vrjbHfox`{vrF00=&8alq|IH?MwQK^>|oo4*siGkqn%lomzuTvo4+1*(rfU=N8EqGy7^+>Lr|&^& zH=9t(8CF%HQ-v#O!!mb8En{c;S~={ETHz}AI9+dbSID)WJ*i??w9d<`a(dlP6NnEo~Q4FV3{pPbyN%`TdkaXBC1^ zdKT#^lD?kapA6XHQvG{$%$L{)dUJkC4aYKS#LSpGpR%sudFNP4?fkx@c78V>9v?RK zJGaYyk01BoArF4hgP%0jzkB^uwxR8Usz+~`SmIEoQPu1mQ=0ZL_Ve1FlyjunHecJb zQXOfr%|C9o!yiU&A5qFY8CA2L7f3j2f%NC(O=|ApWtn&;VigWITSlfb6@6`wshp?m zV6D$)4?_!_@R4Pi+Tn=ZMjJ-PR5f{xZ(Rr9D&j{<@sBLC%;A{*UtSwA)rnAc&S)qb z$0q+q_!$&NbDt4-H>Eun8>B^!ZQ`8UzBwNtU3qM#nh9Lk`HZEcT%P>gj5>wOnhQ) z#=0;!({yoeCV6>oX8F!Mc=CLJ{=VFt4?S6B?~rz0jH-&4qAK+7Tk-+&E1#@M#V9N2 z`ulB_zn!*jr>)y*>vr0@owjbLt=nnqcG`lUC!=cSQ&BbRgW5y?hZtMC)3w%ylv4j? zMof>jThp}-dB)nUDK-7&q1uj%$mHI1ED=wsslPeI7|WT7xHF8*kms;FJ{N&|6gn#D zsQ*>QYt8^?Bo&_Js98tBxwY-WBJBBIDLYo1sFU|dZNfU-YzNabGx4FQsyS1kqR=^T z)^wsdp8ZR$*ikbZ9yaYju428W$5{Wl)S><&+Dn4JkGeC2_R!4ralsol+6w!@dC9QN zA;S*mE1Yo7NQJSna7|kwD({=5-?99@`QlSz!+Ge`&usg-Vmy#Lj0WQ;sEf3)I%qC9ffX6-LOvVHl-rpbKf<;CvWL1c(W*f{s8!ys0yDk z^WhQ0seLwPk9smnq08vkS~At=OnVgCt$!V~k;4Vi*+*$_>yE;e3pHUGGa?@?SK6Gu z6xua2k%9F08{cshx)&Mz4e$)%75@H+`WuR4q{N;MP#1fdz7@V^OZomcRQQR7R$z~E z!puEE?;XHDD<_jRX5l0Es(e7w=(r$h@n_OcO}B0pZBJc|%)^->OD%Qam3hSLMNJFZtN;xiosF@4JU;+a35mb0BI(!M``3NVNEQ&eU43NI&V*9(bQE_DvhpMx$+o z`~v2h1y+P7%470q8xVOwQ=K&}srSM;(~67&m(tE0%qY`Qx4#xrY6L%?o0d|?Lv~>Q zLMy(1g(c&t+Hh1&#%wFZ990QCm8X(C-FJLeEElp&;Azq~;Hbc~_c8d511Fpj(Tn=1 zz`W;s`E_3YZ617s^ug;_2pZw@(vQ%N0yNAV{bCLc@D5WJ8K*pLs48rqI;yG~emr_N z3O%7kTh)@5{FYONKb5|bcZ1}OE^wlyayS#hUPD&YYa=>tWTGD3s9P)oUj!%=mP)Fp}NS`bo(MgP_PWrb04Yw~|ANDy%Z549V%r}si=)pOv zXhtn?)IDP7A}i;pBk|r8=V)H=tJ0y=Tx70wwcJt0w-PDleM>Q3&2-4A!*)I* zb-~egA~+`#sX1cr$YFL$g&rNRup&qCEx>bt9{~=JxbR%y4k;JkMR^_YIw?N{JZ9RB zdo>6DQsu!h;JLsR0`oLdFZg59JdJr*mLj|OxS5HF zpGGbsyBM(U*IV@IyzY~gq)g_Wn$kW!iwymJ@^l=LzPbI$>R4a&OMjM6_U8o^X8fD! zN;L<*mX_*!1^PabNY!~f!c)aRmhgx^EB>L#BW+kB`}gsQouKbIznX3<{z~YJy+9A$ zR{UiNeXU!U{;#fE=`VVH2w8_EjUI}+J0vm_-5J;!@(NsQXB8*L&3q{@qrgQw(|!H% zFSoNsp;_ywTaHOPj8WwNZ#}se$LLb*Y_{nTT48T-M=fGZV*6^&G8tc2y_ORsW)5=>6@h{-t7Bk-lexOM#1e*EV<^ zy}x~}e^Id#|8nRge0+mCqB=@xFIoba>V2DcKL5ApbbeHy33Bd&2p^ ziCK;zu>^XkG+DoVX?Z@t`rIV8s{2w?Ca_m!4c7F=UMp*mo=ZBgXIiFkveF7*=hLyN z@YoU+WGw`Zd^IrZI*$)!2fkei?H9UsG@dHFChZF^d*Eek0YOsKa>kg)c!zn1c~9XT zDfS6CFqTm2Ou{n96IS?aLgt5z%p1XM!ipYXh4{pZOmHk=#h^PIx+_UHlAg0Cn&~0k z1YWaSmboDFGI>eeo{z53qaBaVk+oOp48K%DCr%srA{~h-bD@;V(U*7W$3^;p?J!2n zQ{y2!#uJhFN9NgF$c}z1lnuYVz#{gtW8@K&*^M&y@^0eY#5>75S?s^GQ;Z)j(gyRg zd4V>BM%tb8BX7BMWG;{A9&l7j1s|kc6CR%T+OHdjM`Fc5t~MojdTy7so$#LyWwCYh z>2drZkLH&*F_x-2Xs9`7-I$;*U7Zg?BS>r&KafaCyc9Q>d(JGdtfA_{<#F)FcdcZ; zZlf(?uS9xl} z8BT>mj*0`H2Yy3f?5OSl{^YgFQ*Y+o{Cw^{6-9=Danm-zeG}QN9yja=>2q!@TO!Mw zPF={DRv>@Vsq@*JbUQzi*c9A}A!Kx>^3;WARyb8T$_`X#0?zQM0)1!R&M5qK5I$o( zAEHcRAM2Tg;Nmk5)H-40S~q0uxQM*etW$-*K$d#Wr+>uM#Hh&o%&^ECy;H`X#c7G# z==V{P1A9Dy9RA7~al)*HzL|#qqFt5feJ1T{y$^|jQRplJb+$c7Ijban0N^Rl_HZkXy*o4&c+r*WB zp-tR&9h>;huWu8Etl>SI2!8K>fK3EGz$Tdg{#l#2@z=45KVEF#m|<)=BWf;VXC1~?IXM-}$MI?uAw*v5e;Ez$9` zLwf#p>X;`gp1y^838!xVEh;>;6yLOKOr@)-w>VXmuEidQ$J9Y1&ze&FhN^=n)^^x` zR85imckvO7pQ<5Uo~pynFG-m*?9?q|{UKvh=nv86(+fTN3&Ed$mA>Fef2sRD>1*j2 z`Sx_XaCosD-@n+7W@0MLJ1lRW56S%MypR$(tw>j7_xPB)%RNZzN9~0Sw@A)7aviAc{vED-bRgk&i=9gDk_%1a!ZL}4j{onot zeEsrJVcEAzFUWq#$z)|NT7I0e=dsn7 z7g@%)uybr%uW4kQiOsP7GDK%$-!gu_wlL+6A8h;J(rkEqx2bZwS1SDMl=MP1MSS!4 z5mOx^Hhnf|myV;U_(2&*Qzf4<6%icS@6R!(&@SUk##~m$)J4H7j;RwNhxy;Bd*+sG z^<;a(M>S*9Yfo_Yy8CcqKYxL);@7dCSsC^P#D2s+(A9v*nBX4Dzs`}b7|EGtxO~Bxj3H@9B9=-qoznl z^!D;H=tS}o>zEnzl!;iuqmjbp=ZpF}qV@Huz2U;;;cN93WzL!5>1zi1B4)}!XHsV& zbar)&|LS^^y%X_&v-Y4jtz+~i@z#N$9X_*bk2)B%BWLlSIrN=ImvV-~JAB4{N6zv_ z$E;P9vB$_nos1*8{VDp#pJ$4`X(we05~XAR@Qos1Ryk4?N~ z^^p$o-pU)kt%snAEUgZGX5*Guj)zWNCa;sS3f6K_cpx^js(IK$Qwye$E|Lo8nw63^ z-Tc50C7*sMczOFcHg%l3vVSbR)5a3v*BMc>?B|ePA5=O+De>W^Go-XH=h&bsjgNSieCV0t zN2Q<06`g0Nvd8rdV@w4N4F`am@CnK}k_xaVI`u28+rEB_Ew*!+@fdh^cWNs6m0thG{8$_0#cXt#5>MVR?gYFgcoTe%=!1B-By4$x(+oUZ_1%%LTj<6 zMc+u@P?DZfl6KnzhxXRc-t>dJbozeMQzbpglZ$gN`BOZcm87dYoDZUTJ2;gd{&Lb4 z*P*$T{Gf-km~_Cy`Bivs5IgqjTBP5*4*fagU-EEnApHvu=Yx2j2F^Pk{uI(bzYfg` z^8d-hF-ZUH&=E`YGc597fWFaNm1kd5utkXz!cWd2F2erGc8QH+Pi4FOA8(i9OPu{F zZKDS)Rqfem^&!?MJ9pvl{$R1}bu=B?r_}E?sH*?Tk9uZ>ed7UQR9M#Mb3?mT^{>H` z`a1RZ-(p4ZeX;b6l=l5Yj#B9d={NJh)0B%}_U4BQnIHD&xKmV~Bg%7x>#IuT@UJpQ z$XG0nznzYy?N4k_=MAW;vOP}D6CX5Jmtz(;F8f!p$I_Uk)E>nS4`7c69(3H8CZVdw z4bFZHD_Yr>RePJ9pg!|iY8!jPg~Hgg&AM@HQQqJ^k9UxFJ#Uk@#k+!c1Md*; z1nn$|1Ms^9owPkk;1M}{?NBW`RCHnq&gYOKmUZBrzvL+_mV>1JGdvHjN@Ua z>Pw3se)J;k&if_pR$r&xx#NqhIlgwM7u!7^%*QKfYj5=R!trS- z&Fd1bE^!_cA6u5MeQQ}h3eKTonU_C{eC~|o!#tB`ckbDk)g)_7;(!MBV8Z7OrE;dD zoF^?q)_kHf)*zfy=)4H)#w(JS2WC&F1w4zoW(^*Vbww~Ed#}y<&ek68YFPq<*X*?c z9*40dcsmMjZ(*$$%QrfT^Z@Bsvn{s4JCJKhaXxLS@mNakdRgh(diY9(;fpiIe5d5G zUX}f4)}Hx}nBGUocjmx%o>WyV7v2>-_|yF;(h(ZuaTZmt&IoON7f$Z(RP?dFoWhO`Yudi`4k?;jZtDTRDPKjAK}v`d?TG(zDw+BExah zY91m^9&fao57pN9dp1&W7MV&pGBgjcuOn&Rhv;V{rOdw;n-ZHo-;%<{uVl$*FXPG| zh#c6{kb8E~q@xx{o1SgX@^qG={-1a{E7l+N>VMsvhjwLyVfC+9fMuC_viF)VpfE_@>wBg=dvd9*tZepAqD%Hj9U zab|l1bDYLq}a3AF1*Oz8Gg;qrc`7e?aSR!;Z^%0zK_69nRmm3^f%63o1c6B z65ilL^XBSjCVi29fg9z#p_=;{5qPmY-sq3ZlklSTwn&%%Tge}lJu}8z@eYEFwvzr%KV9( zpWyyDa<=uk8~qd?Ui|Lm=n3}Z&&+A(A-`_ZyT{TOnbLw`fk2YC7`ci z-%7vhhM5nZX|{ty74~y!OU+2vCRJ`}syba^Kc8L7`n;L*Nki4(t3%!!e_J0PsYuCO zAI4T{>FWTt8*@gou>}36PB3jcG4eZx8nZDCgU>v(dwd~rmhkJ%Ma&a*vVWX2*6aBx zm*5?>R^>jdZ9&_N$UUXP%;CS>H(-|4q7(XBCAuw@3w)W9C*|_?#+kOi+)PJtC**=( zW}?s1aghmGt=y$B;jf2#z5Tqqcz>RFF?nH;H9!ox*|Xm?egEuG$m;iOf6>v}L}u8u z=25u)Y5*Gdk2y1GHV6AR_2yj%i%vf9w1KR>14qD7;z3KOzUY=bS{|atFH^{^cIFz{H+bvsd2i z)jLPMTB(QKTxXpA(@(*F^_sHcIAzQ*uUA69R?|YRxkjZX8ugq+teB|7j+!Ww^ed#L zO-WxMolL392a%nrQshshl);@=MVxl^EJb3Cnt4&mC3XocK(2cJ!>%fG3zYUv z)cZTWLui85XT5RVh75GvMcH3dwnpwBiyx|KRdV(luCWwn5vg#3{Wtn(aNiSo+A{CW zMo!_H=w$gEkr}j?35}X2H{WoGhoe@IdX+Ww+oQ#Kzf}S5EgF~eBrkt1`62S>>wN8t zj1%zn5P3I={NUI7R>b%Z&qV|e;@fXefiIke~A3)zWjsakCI;{ z`QmG5AQMTGPaI)G7qP|f^1ahB&z@`DGpqG!$%95rXwbgg*9tNIkfkMK zqDZR~S{I>ZN#NAh1?lE+-wD;ejd1#FOLt2f#Qsvk4xJ{I?_J!T}+$ESkCr-_Gf}OLfk?6 zPe{)`M%t^}LR~p4)^VYfd3A56ZW8=gWX{Pfr~l9ZJ_$_R^|O=BiW_8O|5l%v-g{@Fp40=y(DA&nV$v#+pp)I`28(f*!G{4ZO z5WYP8>B6tz(B@Y?9=|GZ314z9$YkBOtx78j12+1bZK zeT6?&`0yQ`#sPMq2nCgA?EUi)W;NKpa)+hEO@t^3?Chs$X(%@50;SI5 z2i{^nDb*eJT_?IajIJ(*a5Z1Gf=eCN8PnUu4#ZCBd%f`U7kp2phTPcYHr-b<6+UUC z!vEsZQ#9 z?P&c=J13`&D&fUBn%907o(vh6yjyuR57hsf)R%nG_4{IqwhJllvx^@|O(bLtYM)&x zZO>3`|Bd=z;+tIY$ui%hfS-^uNmEb8c4~r{tSDo-r&ggPXjra#`ues3V98t92W9a87{kk#9Is+bL zemuecF!gloB6#-^N179fl;)kjnatHECKB@4ll<~s{(WQWwG&Rpk^Q_1?yB53W+*jg zy>>#{Sr9| z9f1@0!E8b)@&fV}eRyXyK^^zON8U)Ba7OgpS2LgWs`zQv5UkUO&pE_zD;yQh6EhMc zd>{QpDdQX3l&l{kd2_w4yOcOx>J)V~PFwQ5gtWz)T%S+Uc393K$BcY9txgqKS5?cI zt=!o=Z6JqX6(oMB*u%X#WD;z`uErAJ(w|ZtijANj=Cs0pXN=Dob;prj)1(;FQdZ;x z+v2+)HEC*WgC*31PW2 z^Tfh@{E6j!J8&QM;1?ZNyS_<}8SLCrC3G&FouXv#XtLeCB8yd7tv7tR-oKUh$L@1= zN!#*U5bl{;LW#c8Z{3txb>XJW>bGyothsnoX6?H-WgfyF#kXu=Ehm0vCNbNOWL?Ky z`w3*hIDdQffy&IPqD(~Z_~N^VWA!hcG3#HdQGDlGTc4SsKJ#?iaPTn~m+;#ZA7&f{ za*g#bvG;1o{`=@cJ-n z5$|PUFa52m=s}cJbafhH7oo+jpf`GjzExr^rt~{9-iTjnw76quMUK!9`3;St%#lS6GM8^uYGl5|Ps;Z^IyR-v3CeC4 zoMPL>xPe$qWMZ-oHifqEiH(cj(BI$kUA0NwX2x=j=n%Qlzbk)vAex+9cYv#XkLRni zPjEKCnVNj_Z;bIh8a}G3blhU&L1L1Nf|r){wdY@4+b;Zfv8jXf0sD$RvoIf!HPu;T zJ$8|oI67!zcdV}_vOL~8ExR8)>}HDS_N_!JEcFf;&J^y%86M7<*z=I#RKfqBvxW_3VafOB;W7rvkPa0%_c`}ad9n~CquxW_h7@T ztIxlvn@UHUgkEV~eQuPSX35=Dle+6ikZVc>-$BOHsIyFHiCmHWAH#PoxFL^jrN4UeBbNh1oU14@gVm**S{kCJXT^ zPcOCE%P|hh{3!NNJX3Oxw#hx=3g@V$mM{k} zZU#nY)t|(UH%ePMqkhCWs^pxhtLDb6>8|1KrtTK=EB4GG#$q0(T^%=3es|6~JX-3r@GrZOllaYt za*6h|>?hH;yQFW$aSzUX#>L+=Pp5N@iC3Hq>(dl54mKy}DiSl(hJ4SuTlyKIy^5rg zm}{DxJ?yDgMx_Ow8$X#9%XL}hjJ85nmw_u~2}j8{C-N=vZulILx9~b{9X=-hRrCp; zhtL;u`+HCM{UAI(BeKLE|3u!NozjljLB)rPdGM-#XT|Hc4Xq>Cd7AfW!727j`Y-L{ zSM=MhZwE|A)zG%8AO<ozRITW3USpi!*ruOsyN-LV374Z$Pcaew!NZ(c(>A5=c~j;{8TtI) zi_VulR@pb2f zj4`11g^-=dXh_Q8QR2mqlFy`Z;E zc=Tj0>)jHW8**Pj%N+XCi09@)Gba4XJl5hUL+WXn;=6YgF8@$?=3Azy$UyLyA-_@N zgIrWmSIFgO=>^#u$uHWd%a2}9Kar_ToEtSik`=nx{9@w!CTRZ|wkq?y#8q>oFS>uk zM%ZCM_5nsitO1A{z!ASO75$0qm_JmM*p>Z!e#^xzSH$!`7npU+&zRS}da4F|?i@kS zCoB9v`$6q5!3X;YmX0NnX_Jge_+veA`B~u)`R_)i{0>t6s~Paq`1f3M`%AfIiL(&1Ye(@?I`^GPUu!c@4oTc_3z4gdC_lCwt_P8qoV(*GLCaC5(5^dLQ_FU zV*TngdLhl3wzk8svwzcEDqq3HXMazhqk;>~mDs%eKGVlXUEZ;s%k2Lpk}}`v-|8X; z%b0V!rEESX@cX8 zpUb}q9XWHU5?hDf{lIIqy`fLwPXIf#Iq74?er3*qhNsU9e*LEKQ^%)U~S z?4<}@uWi{2llm3Z&rm-?pJi<9;J(en?0*J5J2u7>tZ&`D&;;v_OHx+kjro!Nr6V$) z($cwTt9yJ7;c{^SR2L#a%>|H=RsIF@Ar}o?2M)#;v@JCx@|@ER79P zO5KZ}o;HmAVR!5g*`BXWWa-~oWGegk3DFH>XO1i5OGl;O&~xW%(_)wX(qYNle}~PP zuoZc$*_v8xZ-`i$^4}ACm$q_^wyedSapZl*u#@sTZqTmr>_D#xY18x1m%fSo^3r}$ zCZ0X*%$W_1Qip!)JwN*LQIS7&St~X)(k8$E*Kp0=g0x%IvjHA3I=Uq1e@#+0k+{|` zNdKMTZZ>I^UVDPOAKVmeFgM{}7O|#AN6a^$WnIiVFC*)`YWxx3k*8#hTl|eSIaAhm z9`K>k?v7F7G0|!60oP^{r(|tu5ld(ti!Hnhu5PEa?-L=V?Fd~ygbxS~B~sjXvkmsb zsxq{hTkVb=`seM1HZbllbx2>b_}U^Z_7<_bl)mpOdwU{RSwH7kzYFiOZ|@8*P~uZq z=SS$X%vW;Wi7#nzpvT_brTfo-FS0118^Io{mg9S%8!5Fn^gP>LqhFedJxtzDV4pNR z7S2Z`zRHF3Q~5Ss)~S=RneayJ&Dc5o&^Y}s9X}#(##Vs48L}2<{nDP5@lLFpmH5dU zkN2=2D(4?NbB1d-jPpA=x2wXJ-+HP*=2SV-j(0zkU8rq zWFlj%R?bfGJ3A+^U1Z8V2P<+GI%y*#=bCTHw~Ww|?@wi{h6JDbIz|zD7nqnR0bf(t z50c-rl(k&e>%Z8-WZ&WIze=BrIy+5l%Wv_-$B1pw0l!0=HAowx4@u{^t0#I)N3-E4 zmfG>Lg~Y2E9nSD>dM0_F{=a+AhtKbz`XQvRBqeS)Q_1%C0y^6XK(a^)^r@G46-O zZ;DL~#~LI~{IBp^F-}^>mc&Y8v$Quwa47%JvPUd?544d?*Ge4q?x&wd&(M-N;0ib= zpb_-bVBAy+4XH<+Rn!%mo=KheGSXgi2K`_DeQ9%?-0m+FH$yRwOf7GffGGiiQrRbsPUjOSg_He;W&Mt#2Uu=pCr%3*ldkW9Sm$`hQ_@!2ji@z0Hgcp9- zj`_jpXz}u=$+|@7Tm6Xd!1ZCB8l%mcfiwLA6|1O|efccS`CQ3m+RXPrZphtR%g{89DMMy4$AZIZes8vL$;#a%M(TL&Z`o_+z{kgQFIm|K}+885c@-p{#oEY_D+4RE)>B4g^jDPxH7 zkt(%uaDK<5d7g6fYMH8qug|z;SH6+fbHb&+)wYE%Koj| z0X-LhQz2!@Xr<7RG%>EsE4A?Rr^1)`Rcvn!d5nWg-_6BR61VKiA%Eagr93h3UBo6H zlJYe1AbNS2a@`hu+(H}J@s&ZL&-v6Fq(3iwlYW!mq?^c1v#N57PyI}2=00-jt>fkn zIm3Fx9gDxX0e!;XrQu?mFQcJTe|~>^7wO|7V`--r`Q<`K9+I?iiUCT#*e_$} zA=byU(GP1VHJf#nGFdB28RPC@X@@hm*J&U7dGEK2_3%j#m9{NBN`0yKW23>wSKkSp z@Q9h0m{R!O2c1iThYq!E!DrPFzoSY1p9+2CBYhP6T8ocN$=z-bUIWZG9T{W4o?|bq z79R_2a<4ta{gMFoVIGG@w%Lgv4_SeX=?E{Zoi42uTcTasxiW<|*_+U@skHMk`nbj` zGbyVfc4YpyYKZTvytbCOZCR|ZwXH233fU3b*87SgPwYNKox6vkt?WT}6r@bxTys`s zoAUt~zx$iT$6uP~(#p$u2=eV%>&9>$Yh|oZKFceoU-=LZZSq^Q%@UIcPx-2hnU{G> zc%OEa_xJuU=@(^s>`+#Dwa@SUxs*vA@Ufjs>`hv+9JCoL>`yf*cOPEW$UH>+3GK^& zc%b&kHD|E!EBmXWNABXu9^a*wP8cwApp78kZpD?iJuiP&C zJKovo#r^b0enTew^et9U@Q4ex9gsPSM|>H$5;N@5_W+EH>^W%rK5H}#dVLzj1|qJF zUwrT^v98x%&l&C})L2TT7dqh?@Fja~>?N@em65$}Y~Iqi<3KfjERaIviA55ftx~hvprp4NA=j^JMRc@N#?yQd}ZOQv_0|Z zHFbl`QExY+V|3~HvBriC9$nTM^^S*^0x#ji>+$gB3!d~%^i^X^4W8E?dvZY&hAy+V$AuU=c!Eo6Z8K9^@J(s!|k zlkblkWIleIJvG-4BP;Pq_}#bXOJ1pL_-=~dN6~xBvl+88Hh1r>)iLevJ++psi*`R- zYl-jOeULcynOkJd?L_1(mU|Nh`z6&fUUH#SRjwgb&HYmB$2R4zh|mq4DqP4VveiPH z`)tvnAiwRu(3W+->`NLY?axDZ;QqY{ zf0nTYFZ|}UBfr~h99-a3gC}k1`vF6S3XV5q!)Gi<-(m6i`svw*RM_Jy<>#x&%TTS= z!W|xo(fHQSHfxlc;H~)-TVULe|#d@VM38x23n!D^+TJd+(#x{7x&mb^g}hmVbW7 zEh6jwyR5;!!S)`Valc!6%jT}m71m=L2L^SG6}sB|&foYQYh&N0_WrAx#Rhu%+B-M) zK4LxEHPGADvqD*&eZ5`H*5-|0?4sFfwXt{O;JS^S{R4fQR#+YFy}f;dmJsUdlB{aA z_91J4`kPmH1n1K{jV@obe5=lR&{q!JKRB?$Dq>Lo8hG`c4}AP?YfEome^+l;r`6s) z*fk*iAKcjS=;mgtWAi}rWAj@UwQODFHrPqd$BM*|x*=zv#Yyn zK)AH}+dCfZ8kDMn_wjaeA-}qB^I)?zIPkcj%-^gDuU&Jus72lR=}+jl;IG}f!n*sx z2iM*8>3g=x`_uQVZng%xHV?KB3{q9s6TJ3E+Bf#l+4N7ZPPgm!rc2@|LNxOps z?Y)~fZ5%{cn~+`K7J79}Yr3*qWvz!R;%)Ef=-Ry5>gen3?%CL(#iQxDx^Nqwzjc0x zq>2spbcv?7Y!*)1w+!~(+TjZG*3PcMu8zTteZ8)NO7W1Xr!|*fWcbMkS6B~jwc2|- zk*;e=mY7&yuhsQfSFg2R21EP6*?&o*ap9_u><+IETXOMc0AJ}r7+~8 z%lO16@4x@kMM7SFdrwbahe%czT7&KDd%CPrKd19oSQ|I>_lO%1k;=Qj{gEyY+iTP6 z>n?gNYyIPcU7jVh5A^H)ReQ#!{h2q$r9k}O3JdSszKHRHYkOp42ePsTH+0b`t#}N( zc%P6Qyl$Vhc|+g8AZ2d8sBFss{rB8ewU;l>6n2}$4c}bKmRH`fp$oURWs}wS=r!$3 z=5N}#c~kpf$A+TVRL8DQ>2Y}1CqKD%%?j&NUA@|U4|L(|HZvx4XZff4&h;=jX-3K& zz2tipKjE3fKvzfK0LE5iK+DHU~ct6U;iOY!I(%YeV?CTip8l=6o_lSDd;)pRTN?iD=Qe3#G z1y^oDz|Fr~rV1^-Yw`N}JNi1cFx>pR7(F^XsQ;KJY&ZYT2iNG)>9#F`{q#!MS&uI% zn$`+y1Jj-k2$(4bbOHvpboQ^)x+;~#q!e_ykW(ES9$hEX3{&}*-pySDk1_m3TvmVA zKu7|~xqb`(GLANG?(b=TT*ea`T_-l~;`gG( zfi3-m8cY1a;D8hic5J0&dw#JP zogyEZ7T%Yu)Q0w+>tz?4Ex*eWC`+I$fwBb35-3ZcEP=8F$`U9`;9pk)avU4xsr=U^ zTc%c)Kv@E136v#JmOxnoWeJoeP?kVh0%Zx5B~X??SpsDVlqFD>Kv@E136v#JmOxno zWeJoeP?kVh0%Zx5B~X??SpsDVlqFD>Kv@E136v#JmOxnoWeJoeP?kVh0%Zx5B~X?? zSpsDVlqFD>Kv@E136v#JmOxnoWeJoeP?kVh0%Zx5B~X??SpvVR1d`t0BKe`<>s5NO zc3#Bjk0%mwrQ-2IT-6$eu_nI2g;nd?dD9G|fBQlY-mc44d}&PMtJW9aeQVnl6<>Jq z#v3nQEU37$_`h!X!2t_uKx(bk-`}scPr{V1DJ_4|#lKj@zaEdiytq)dLswGE-2x3K zBRv+sW>z3e!|`~}_DD&2B-s<62R|TOx+0(r&7LCVS1x~7XqNh6^ z3CH8xrF9WuPj}CQG^op^(JQT=NdR{X8zEgj@URkgfcakouKpqBYyRX%ApW_()_7}c za(nCc)>dIA(z?E`yE`5Vt?%yE^t%V<*mmTOJ8W{}k?l$Qx8lj=-QC^ER^X7blXTVI zZgJEiM-En(f=%>BipXfQGU+`a6c)7{;z-9kUKt-H0gd;95br1CHOgBqN6LwS3vfl6tu`?oZ_ zJ`zf{3LJ_9w{|BZkz}{Pt-xnde*}T4JG$?%1qO^HfkTfigVok6-SK-Ow!laNTx@82 zYpN9sO8v|DjViRNma9-a8RDnhRk&5)9u12zG7iyaWE*AOk=|vk@ojf>Z$sU8#FNV+ zS9+xbq3-STkY{pU z>+*+@?>3AZ!XY@-f4pS?Pr@HyDg4&sZ7m;O_L1cuz4NY*ue|#nx3d0M#_rdOa6$hS zp$~Y=FT4DI{B!B@Z|*xb&nl|V;GHUrYbixZCwVOLBfJF`w;`(6e^Or(Q4IwZdd!3!Snm6gc)?CdCY9#)#ujZM>JZU(}oO-W5jH|n>G)1=dZ;Qu|IB9-A0%lQzGu(6Lv`j2VJORC7Df6u2v z68uSj(ZP3Bof!=y8$^Q7VVJ82&2 zcbG^2dAbXF@=uW|eb@a5SNi@Cu-Gd!<0UlXB|OB1XTgE~ch``vP9&M4UXS1`V-&#Jr zuhvToqyirPNz&d}o1G=?iKPTTPj1o5|IST&b+bU#q=m-`(s5nNKa=A$r*oqE-ygVX zudbAcuBbbwne_YXT7qvC`}GC@GS>JTNF)32=6TMM4)f^0$##>*MKXlG4UX^@^y-d~ z_V>{Yr}TicC~I@;j0sIoE^|ch(jGQECr{e13p1Q0*UgvT#abYMN2iIT*Y;e|1$4%u zg&)kdNQ-@9V{;oxU(*NdT3~HBq>HjKNZTH6kn|g*<#z8G#s2o; zYi%(v8Ze8$d3L`F7|6e_j>qC@ezbyp4ci64JgD zMiHAy#M^pr`|8))>$}#rSKe)7&q>aMzM0n!GJ)M0K?4tt+mfN zGm`|Zz5U+zy+bl*@3q!md+oK?UVE*5&XBubs)>Fg>KYqbtLDyJxPH~zjpa*kxpCpc z>o=AQA#PiEhgj9z)YP!fKYdlp#&Y*{<%`z0l+SXz=j4tPQ*OG3inGi8Ya7bHa!cJ; zjHas_S{fSHZ)j-RSpL<92Ok0LSJytwoM$dwcyl?kN4=?`vEjju4XewW*R5`7Vm7xd zx|><$jzc4e1$24K!y6y=m(R-`S3aYBt>3?4-prW~k)$&=u5WHy)!i$S@YmS7!z|<^D5Ofm8F&8r~5*alox75NQ7TlD9Y5m8`LK% zLuT=7m-@|0_3(zbei(>5o3qrb?u)er;+LUx>zY_oAfAWPcbCN0&Nt_yWLgzl8Hg7& zdjjWOsNT^KyEAa!jnbNi*v*0Sl_+&J#BKw52^DiA1up$?j0eLNg-^OwaT}ZDdJL*BU}Pv+tvUo zgh?o$gEukWVmV;?wo;dB?^=^ogiuVv{5g0F@QTS|s!{d}>feTc)c>laNl{FS$YQ*5 zQM^^+m4Io#p#HV?u2o61$z)bUHubNJkgrR)d`XKLXfcl3TWpq${+}1+tCCq3i$xI* z##<~I{GS&!tCCiWB})-b!kbO#e!0i>ZABE@k;|ZUo*ha`NRwZ+6Syr?7JFR`Wd6{XoxGIf* zF1M#y{{QltK6%QwuYLZ1mx(*aLE}RF@aexVEc@QB7m^R$S@-zek7XdHFoIhIfY>7k zOfAIscKtKA_-ZC%3J`n8WaXqj3|8R`R!38;QV3#|hNzJ(wr;zBigVR&9g(*{Xo!!W z`r{OF%%US8?v1hq#GO(@oo`vSYU|e~Hk}mp5^?YLduEAyHXh{_D?#a>ipgxrD$K6B ze%=k9`3tJ;!ig0&zUUH@#hUHPFBo4~G~p5j>r{wKGA{*-AFe@Ou3~vPxHY zA&QITUEnU8kLaBij1bkCR~n@?+m@4?XCLQq-pG_77G|4Sn9PvSWX_=vMG;nWjuRh> z_Q3`~r1Ek(oKhEVr&bW-w1O*Fhh%Am8WbSTMU*GR)Gv5t4lPyFg&TSQg6yZJIA)fZ z?^H3BCB_E?FCyVD1}~zk8vlyGhfBC|acua-_*@MBH{efWfc!-;7(s)no+^r_ifRmO z>eOliQw>NSDZ`kgNEB6z>LOU#)S{xPMb%TQi=Z_k2Nz<2#>5fqxM>kcK}ST~63wU$ z*idVLP$3GSndKML&&Biry=7%(VR7Z<356xag(a62 zmXy%XWhI5hC5018G7)Leu@Tt%Ey9KE+%8-$`mwu&%_S_@-qR6j(6JFVn=9AmvfEq^ zo6AK%4wudDvgNum5oyq|5qWtod!B1tp39l%a?y{|l{e0nXLn^H(x77_c)gGDk?beW zF0xIwWA=3P=Eq)q?6qef+q^k>C>c4H+}xN*B-*N=k*YSnSG83Upv@%#ZP-LS9&8`U zz4mM*>CAS1v$wam)#LN|JjI)ft7lic-5XB!Z&`(Xam`2J zXP0}99rG-IHqbwu814@UlVd?*fx`r@n~RG#dy3J_=Mz4$<fRk?6?VceWKn?)ZuVAfm?+y>8rpU4Jed`;7pDZU+&gc zw_CVHV`C%N8yge&*C^a=;a2-F81?iPyL~;PslM%* zu2xZMhnSG(BVS`{qwgbe66$%#mk>PziNt$7J)-BM!6R?uUe(ys)6-bR{ndjXy6-*Q zTEcZ|*V@~^p@hb{Q}P8GSDg9-d$&OA_Ywo(2PWV}aEQ<<5Sp8=i2v z+mLJ1{82NK12>Ex2KinhLADA7@Q?t9JecS2yI03WiQC=pc9+n);9sf$BwA=_bde%@ zpeGt-vAtFF664LHL>uSkh{w9XR}C=fWwYql?idT#p^q?DMiuCMo9jJ9$NB*s-+MKE zwDnX$1P|Iv{q&&Q1m>SjH{Of>;`Ocdv^2KZxAbli3t;ZOy>EjHen>z1ofxAIILir! z@=kS(J5uZ+ML|f? z9X@C!xPAev)d#KQ{s>O@VsL?x@Fn>c7nd=-xR~4`T}kc_aNN0$4+2Se8N-R+b@Va! zI(Ib@iE6j34++U9DTXvW!NHZ`bLS2*oO&ZVBGKuIKXFQOySa0TFG*2GKq333QniLB zI+9A4S05M2ozyO(r{YQNa%vaB2#0ldc>iIntJdD(-eJsOycdoy4E13rfd7y8*1O3c zW7p~H>)QbTj;pOcjAo<~5husl>W;Hn!z5@`H8u`l{T0J+v{Ji6hhQ&OJKgKUQWjA_*EDY=Ghk3Mjb7QN^k?$36;E zwYd0@=a}b^Mi~fmh=IM9E|Zl54eSVX$>>231ZZk0=Fp1-t(|Z6`3r`rC3Q}ZM3sq!g3gV9`vPj;#s;y1yjyi5@t3q%# z#sx*guW7b`(NM^vUlh~uF95~GZ9RL#ZPq7y+B8Y`_8=ng^)NA66~Y|eZ(y1nzUW*y z?!dMQCx;7nx)4jqOAmi!4PIE|uA$MdK`Ny7bPVnqtw|4#7$qa59!>AXRjpE^8jeY^ zkI~iEW3_s$R*ljwLnp*ebS0qMxPike495{d$hl1P5Eoob*+y^!N2SeHt6kcll+YLw z7xV$KBou5g7kt1P@WU4eA?Tx?Yv5@|Q;iL32*D1Ar7Ut=MyE^}#|$DIK|Ds6$F~=w z*z5CfjUzLT&8V92ae#)%CsmViiq`H(k8d91z?*hptp^wjUy>(9Z!&%(Qp9kGVJI4- ziy}E0%TY~>=QJ*e>Jk*z>DEK+DY~PJ$AFe6xkmczdGAP@oezT;hX_;l09-v5m^Le$ zH!n|nNi0ySs5VZ9q zbR41<3NtmG0f*oaQ4V`T@T8Da(;1AYiqs^>V6_T|6&J>gMxfN9aO$4P3`ziwC*FIH zBT~Xr7>bLF_~2rKFWRFq#ecmFJ2maHuPJGMw<-$cTEmW(2=n<5h)4Ww+9J zu_dSE#EMOu6_^1Bi`v{$(qqgtZPuw8lEkzcxO#l`)B#NjaY>tLa7opOOR7d2Q5B7f znqjL-uMuSm*VCiB4G>c2Wd0OoqZxco!dKr`ujvdUY?+HtW*zaQXq&=q#M`)}WNB** zvgkD_nO;N8lcpuYrF4dj3_m<$t(ZxQ_i;&IprN!?jDh)Jp|oA$(oG(*I$d(F*LDvC z?Zf+ekM#EPnnvi(`wE5ca)2q#(~PC`LW56@fof@T!X^xxM_G4a)VUtyQ&|hK$TsAK zZ2}vj?uiISdyB+z4eO6<;c!oHpS%9>llI~TLdcr$?H?^*G}|ie)mp>3jeU(A)N>u> z#y&3P*QWo|vjlnn!>06qP|E0QI1PlrU)Hqnc~IUp0VtWk#kEYz%)~;H>6ChsA)zwW z01J&sE>qg`i_!P6)|0#qGgSYOA-<%f)FA!R!+S|f!96aGK%1noPFjq;IB7pE3bP zX`W7tHQ3o8#vNc>DWb6jL@Sx-sTkMHR^(%+k&tn%#EoO0`g(VXq-37~uO({`Q2uaL z3u&d{QMgAgN6LZ{hGf@j8JQbv91cq#9}F00n7S3~$sBc%me9%Wjj-6LY6VL1WRgdK zK1%eA9drX6&;ImjZ{tg6@mY601AI&lO6WOYQmYG*nFi9vAMI?OZrfvWVvYih!!$~G}03cH9dy}L3$bqWy(A< zEs+$QN!Ir~DZAHmNiA$byj?F5+9y^GUs^&bu!8tX<%!0by54SdT1m5-)?jpMNd$WH z%>2^hi$o3`ibQlbp=X$ygTaJyW*62Sm6l~%wJ=xcd8Qr^Yni5j*K(op$?0BAfU;7ewreCVHEH_``=w~zGb=_m(_oR4bmR?kTF!y`Q>)z|w+ z=&F^ns*hxUGA~W_M^B?Lowy`k5A1Yzt~+;qKH`uazTc2f!;i{Q_5OfImTENuz~rH4 z<&xF58BC|V+GPJM3YnK?e_TIwD5)n~jKZF#%L_ck#Cl4HCu&d9##(mbp7gq zeJV-hY<5&WtLqo0S;Y#~^l8;{+RUt$A1?8bBymb#0DhE&Pd;>r(exqXe4kO5Q=A%) z#Ajx>B%i*d>5+_KAK*eh-Z%(!$vihL(Un<7nm%aCjrm7=RLKAgc?byuFzV8NGIL%d zP|~wrE$t=8C-Yv-zVysjOMUs2*x<|sP8M}{mO53E2{4|ZWXKQO!+2BkNm*iseSki_ zPT633-N=Pg`jBa#Ooz3sGsR!P4W#!+{L<@qCY)g(P+Ufx=%q*{rxobe+&E^33)vh9)iwwA44B;zIq+&(kw#sfjC5&dcX8FiLpWbTcJ(7Jruoixdp zR@e3#9cnxh)SGEpICL#9gI;g16Y|~2T*u7DQ;!h!?lLoSdSqzuXOhgUoZ1`Ny@ogF zSszAjJ~BHuPAUv~y}d5KCX$w2Yuc5MCK;uVPotB!wDD^2%v>Gk0XipcpL&F;cdNxx z23JGhTJ~++Gzz1hnYo`lnVGxeMN4@ZjJZJhyOF@t6SuxzxF9%ox{Mq?%vFMLs%a#f zqY`<3RBEKUTE>)0=CLEmVQTy`6MFIxe0Zs)^jyUwRXwQ}dRDK;>)?V^o}RI4S7vID zC$XH{8_B)lU*UM=g~cL&w0cI0&yTn$d^SRAl;OnnG(YnRtv-Lq^z~GqgS!0vtKF3Z5~Uzxj1 z1KpEmEm3c|zP2`^e-otQw$<~>wXaajST(JsymH2uuIF!o%yeHjv$6`sd9!BCn=`w- zrKx!XzV_iSzqxfodBwO~Q5vcdPxp1ZL}&I@?<9lS-P=T$t3A8>TcWETw|3EW7Pp}2 zx(l}k(UsGlT^5Oi@a2cT*R4VwFJ8YwsN=-zYlWIEUVl!giikYb_jEWoRQcx6L3cQQ z>gPiTZ@Vib%-sTC+_*QSjPK49!9V}n6}db3r%rD{d%yd`=v9^uZ-M*6I`wOo+FBGV zw!|ucbBFEKL2p59zAU?`Tq(=tRK9AOXgcZ1-Zatu;lci3WJdC*m9wpB|IW>_&W^nk zEd+NLxOaM8)LWgpDR=8WOZ0*{+2ZK*+9hmr9>JpK?JFHiwy$(8F%S**t^2Ie1Ln#w zx}*;~eYohu5#43h1m9_|t&Q$5hZIp4N{YG;uY)^uF!Rjrbb453R{}*l9 z%`N9b`&}(0&T8q#PX8TGT3}-@WCZ-Xq*wWZnrwQj1mnNqv&L=$l z`Q_v^lk8KZRW6bOUL=~r7FX8Rrhy$X`?PX@cv_Kv&osqF$pm@D4E`+<^W)gm8Ae@i9w9S68<+K(r@wm zz7)8G#&Kutj_Gigx6UsSn{LvUd--+hEbr|5XFoc-WA^`;{fpTj&#str{hWK}EWhsS zbG|p{W!&GM^M^ST=YDPO^6S$7{nOm;x%ZO;`bvk_QW0qPCb#bUgo<0*y>J#57>4?H zvubPGy@?KQ!jo*a1drbzLDBu;%USQj)jSsYiPHIiJ-Bjk6wnb|d1e%_Ah_~W=v(j& zHKI<9W2BaL@5xZR28c<(iBM1j{9Xb+?eKnDVS6I%+;%f&JEQZCTP~#~)?==dswMBS z9~C?4c@%AF?27JRSc5Ci#in+z&!+no-7{@;zpVQN-wR?c=>7N5`4RknfZvbE!wpAw zU>-;GT ztqp8P&1#lMY0e7mG{?-L-5D)=CD14amqA^ZrmO1#T1TDU z<27|^^9Tuwp|4R4ib)N7A@40j9V*9SAYEV2HJZ6g-4q=pX+i86ZI+fN!p&EQL`_|& zJe#I`1pnlwLiGan2U~O-+FCs0HdYWZ2*;*9NVKu#w4d>O{*v|$o~38t_}je~LQY_4 z*1pde5x6)n+Lvq{-V6FX`>2KVGojnSg}j0tFl(}9Fm$^H7*BvvgP0KdiiST8rf6_H zv`PbfK!8r~nOo~ZPiUZ5CC#bOHVyDP0iZ*BJ;|bbq;C^6bQUzaOWMp3-5=eK8k{3F z(Lwh!felSMG}d1x2y_|xnFd&_176YqH|l@}4N$BDd>SB|03*iSaSP3?Ba{sqD-^X$ zKp1I|MDZ zJr!G^f%9IlD~Nbsa42Q5>owT;G}u)d?D8~Ne#|-DCj75Ww+esnbd&HOq8$V~&enay zw9!=aMq{lgYxiQjSSaoL++mZ~8u+aUdgIBKc&J`ei5=08)lhqQ8b;dgJ!?$pUIGMZ zpE_HiJQ4Q$I=zYcSl}x=yjG8G<2_{Rl)aiK-pq$kh>K28#kCXJPhlz}F(^Uev_#l2^YiQ7&clYQ8w zS-wYgOo%aYWVm|>7{dQ@KxVy@DjlHE4fh2J0QWk>B5wnXra;rlwHK%t-L}thWKCuT z>nEe4BJ!kvkOpSqm5-*#N(f`SI8i*5rPPHe7??pqKxpsz*i9YYT*$&Ksr`A`-t0}( zg~an?z~c;8ol}sdfV>7waGU3KH2qsB3)&|BZv&YcLEK=THUe~-If77@NjCltH74OM z#433_5JIM0XhR}mJEXDeBC7Ky%Uu$pU{PO~=e0MzVTf{5hA5w@%!8`Q`xmG)MHXij zMt_F5;5<9grMfbq#e-`4L}A$`vP8MrJ6Kx_1%@!Dv1sB<19!nR>PrYdb7KoH%2ldh zOlD>;O;o5(^%0MZiE=)^C~272XHHIPs0leC&CoB8v?_CEFeP%l`m~N3ulkRa%g3gF zPCI=>Y6Fp@x3o#!Y6uO7V#72`hY#(*`efONiVmPT{1D>#B>AD=Rg6r^3}^BaqLj|W z@Hj6LjD5ZfekKedPE;+!Cjj$^52Ss{n!aXF{;xa(HT%|h2&uLlF@REW`7~`?}2$P zXt9SQOn~FO!F$HJbyhO^8;lKA8e6vSA2EXuhpNQ0+B00pwDuaB~-HKVNRZo^%F z08uD-;gM2_&PW6=^21MqUh~tmNv?k>V_| zj!hXM1p1OD0l{^7$7w>OPisp@^pB%YakAUJ@Z97PHc5}LLC)R7qvr0OQFC|mShGbl z7uWXW&z!m5GV%~}AyORYB#4`!zJvYkUfN@1={$PGK^uk4>_j?J)44HS@1v&k^Avdp zP3I^@LVf96c{cOMn9Yq_{|0mUAAj*&K0PE2DswJlg|PxU#hsp@6WX>oeYV84jSYeP zkIN9qZ{2sw*vPV>Zfs-}W06JMOKBrR7;`QaP@h6TeNqpo2Tsd?8jBveC^jF?RpQ2W z_bSfmM{aljPB5OYbED&MB!sXF&2L>`H;&EyB2l;5J3y%ph29V`of&N|i>M!%JEt3s zs90md*wfL#5i9Oaj+e)a$;;_p(4EYqd+s!c|HEk}zZx6ht(2@46FoW{wsANN%hSSP z43&ux#G9P*K&FzUFx=ObRKo(U2p|bYUSBMOP&#fhDSI0=Ft5mX=rNO)|{$2U{VgF4+17daoVOYVN#9I_=(z}=p} zfKH@TF15?5+*O0P01H1ejnGn8=o5;hb3)9m)WR!p02uy3bypqE?#wvK_2NuB$-!X` z91H?kK)M2~00+equRw27%>_Jo#HLg6PzlBzk8za5;dCOler#>rqPH%`iOy7S0-GuM zsS1UR^VGZjwY9UnapF~aF?=rL*$p35<)&!pt*L{}9L5R7Lb89K2*pO<5F8qeklGL2 zD5<4q8#RYt)}_7znwL@^>}R>nBjql?IK^j3ZfSZlQ}Xy_kQ@_$cn1>#J92LGq?rVn zNNr-Y3D6doT2wDv-z6y#SkR;jNu@L=4d?kEm&%!v%++^_$$6419ql~nXi0r}fcraz z)s*HuFBs1A8^mu!uJCn&vGat3PCez3hZujy!fVcx#)Zir={(W14Dxm7$$FRPdNLh7 znQX~Tw%`*!GNTi6st*>^ejLL@WS}_i!@Q3GB5pXx9&7|WD~33NQYDU}C|ZI$;ZN8A z${2N>y7V0FzYnoz|4hQ?&lBPGpT#S1fl}KEu|jzDpVKb5g`ZP?9iRR;&^N8jPH!%D z&)oURq#qd;#6gDTe0ow$Z6NpA@mN*(&g4^fLpB2dK3X(cDEfEIsz1`wLlO_&m9ZA)?VDoT)?x zFb1L%?*XxOM6eM3hcS{53jAS^+U5_BW;>`JG(?VFmWj(8POcsz40DJu%$;M$Ej1(^ zk*a2+H!pl*g}IJ*$U*Gy!b~EL2qUX#QL${$7+a6b{)qDk_+#|96_Y> z$RGg+MdzSvF%N!~qmA>i3B2xy4qV|qFSi!ntF>@lAKTjTP;BgWW4dof-9kGhPr2D^ zQ1QaPR`T$+z(7|94~m9#osgW3M$Vw6B2YTer|Zq_=lWat^zV$l&l~@sT152jFqDC{icnxsodHPdQOrpQmT^#d(8Xi58g>zu04>Z? zf93p~{qd)N0)IRcxmYB$f%uKsAJ-F%4Z;#VrbM$$&@^TgXK4u>i6)|F6dG+JdR*SI za4@MCqJMycp`@L|9$Jtn(?fjqN<15~ZC|OUw**(6W6Q;JT9J+3UWsl8zY)<5pL0Eq z5D9_J7Y@cK^cj1D{*IHCln_)8+RohSdo z2rcpH=SFBpaFXzOdv@&dY1z&v#PsQ2NUVNXd8BgKltFBAB9}*qeE85>!f_GdyCI>zYbl(Pmt-t$r zR9BQmJfhhYdk`M%c1LGE&oGva8#(H93yyZS%QTAasBpr!C&S z-;Ckye$%|HuDyStT^#@u43pzOMlD~AVZLeR(WO3aYt{q35hKI6n#Waa2_MV04O3tk zyR=U4vv6QpMWERnK4uCWb7~5uSaI?0H%NwM?fcNr@hAK1j<^5nc>5k*3Px&D9H+6R zJ`5=q@9rTM)P#!1+at25MX*xo?U8WIP(UGTr2P$uG8j=H)d`a>Co5WuN$JI=nml?X zO}_4QdmikSUvG)NPVZNS-T=Xu2*@wO6@e6oLR`+_a)QejatSV1#jX+@GetZF$4d|Mt3``7R4q`WF6m9ey}9U8rik3ZFGtk>c|`pg zs&{%VNOEw~-;BG#Yjr+emE;%imP172t*%u>PRkOnw&NYW6Cso3M97kT0&j|+pwQJ~ zlIL7j%ZU_;86@~6l3rv6O1R%-&u!n=MZqpmI2OxtorqNaX6Uqh)h6}C{|7nLoi`E6 zp(kbu^+T%TS#C|88p$Ee4RHoXkKBeTpq4y(*Mp%$*fu0#7qtNyJb;V67rl*i?O_08 z#oRjULK5w<&t%1ub!t9gxLRktty2va)=+_zp*|%;HDsW<7$&|XUu_C^CCi61puvh7 zd5(il1}jV`XKQCVHGFO-Pxtt>LiJpt-TUVb@1NZtro9dJFE;93f4{69HK+uk1gJU} z#p&gXI^*rK?-H#Mo(`+`(5nd*7#lfT3Wp$sqXLItT*on!mgwN^6&O*hmfv|NSp=J|0&S;&p1F zUYCRtBMHTCOI~w;pKqX^5{h2t>0CMdSR^@q3EujGcv7&B ztQmsgJ=3OF)zz9{In+w+xR4=M#TOIn1`>mhW}&Ebf$)-@6eur4pu0y4^qTrErjs<4 z6GAKXY+MQim$lE_ez?ng0!~Z%9ra02egUPibQU@|9wD7em+tZm>0ZqmrLNc1FB#II zmAXQcj=q1(FJt5VCq&mUG)wd*CDbM;Qc&LqBMWAMA2uXWv4%EF%o`ep-)Z_2VWO2v z$S&XaeJQ=!es1Q_-ULo>_H%A_j$ZrI`}hHY@caVrtuyCNCiy?(kYHmJ$5ZE4*q(~ zV8+*D>U`%`S2nC|=xq3T!@-8r4Mo1#?+oA6fTl7=MrM*w|B*NuC#JU=NW8$GP&W~h zIw_@>SD)^4e}bJG)omt3=&qF@LAI+4QQi4Br+iU9z}+ul$}7o>9}6iV%05 zQ~X6ulLF^Vep75}#TL6O@ZrfoZ%%Vz#d@ujTXDi3;Ia*0K;kbWwNDNe6f8%O#w-IL zDB%yxDaI8;wgc_i8U^}{AW{gNRt_BH&Ef(gp}pn-MjPz|r<4O9q;a^A#zF4`G-(ux zGzzv_ywFMS!EIl84v+3Q;+)+F<=|m6GPwerSmP~{P8^DBPw;R6%1@zjD4LLQE0s)M z2S4yiK)D*1Pu|0H#O}m5Am9oMZiRKa)V(Ia@b)KGNQDVWQc(u>#}aG9NeP^@Jntoe z@M7#Tl{%$)^$0&+2=`CWC%79Af3w>o?&PxeeyG20 z39BU72Y7q-3I@Wjbf3t>_g`$ZlGLx7g2%~FQLm|C$U=gY;*o&%k|8iz7Qv{X0u()? z(_UOA)D;r7j!^nL#(Pk~SO|TUME?#DxCw$>Eg=zVKwb%;$r99+BAOy0KO!P>tRT8Z zf;tI=x4j88Rf1Ym?XHy&UkWl!LcU7PAUZXxl%N|^M6)DhCK2IPLQT@y5_%gyHPxM8 zR}x7z(*@@RBDPACZx(^ld*{!!uumn9gw@>@$D-u_%4q+ki-c+1u$`rVxkrtK_op_;pKB2 z9qK?jwTf>GJD+$5#{fx>y9sZEBt6$}!l@D_E$cuMrhxcDe#wL0mHL>D*Um+M#N@5c zZQm80D+h172_51D2qzM1B0;N;QrUCc!p&9$vY_V_01!MmImzYNU7g;O#Fe6|Q+%3* zhsr_kK&N+Leva5Q9``Ia){w}mQ!O}ivBdHTbe#tJlzIURVwfJFpKJOl4>{)I0m%0I zn0TcHQsRuyLJL`~B^b<;9z}k{R>yxBDo5msyz*r7GBHt1!v6?Gf3$}FWR*o^)mXE# zowlS-A|`>3ns`9D({!gfU|F11 zYR$`DkW*vFADD7|T=2*7b%ixWf1HqaNu-#1yMlX5@x0`(;`#h%@+|tRc!~_3vqs37 zpLeDG%5hgZuGGd}SW-Btu(S|kzfyctS!G&d;jcQ0UpKze_-Uif zqJL+6HDg@jeR26CuQcBLh|8LlXU)Q2JH!8>LT#MlWD1juKXZd`wmr(2V(}-@j5g0c zQf#&1PnZz*`|wioG82{F1m=@RQvEbAhWeSb?v=(H*QNSd!x-wvz-ax{3oKtVar+h8 zMAxOb`58mpE?xght0P0bspuUh}eh6nu*Kh)Sje`Ia}d`Wx15e0cpjQ8~jc)On)$3i*AZNlh;pf7`Iji3Dw6 z;qi)MoMz(MO-kIv})h0?lW?d+zzBOd3bf+dxQ+9M2oP=kiik&XSi<&(8vdBF z0Hn2Vo4fL$H~ZyuGS`_+uNYWQY>k*=rz4Bi8gtiVAiJkOI-_H9)joetAfEJFZn`OU zaz@83%JQ9}@(}(j0|k^5@b!D9tuXKW#qtQAOz$&yInlO#PdI80yl)PiHT$hymf!Tp zY!!j7a=)poX8FC5P<_p=S@{w5W7AFr51TqmyEnd`Oa}k>^r5FCk#lF>>K2YjS9YXJ zK@zkyc)?m0@64LNbYXKv=gp@1H_vJ=*}l0D0_+IA^5~AI_8Yfet_4qomfpN0wB*Je zAz{*SmEj#bwtH)KJQd!dE=%qdI~--(H`lyA`_X^hv9-s9;WrP4?i9fju$JKdtCH2~ zBnFzJ`KHpPcP(BLybyuI;w*u#tO}X^4f{k8Q zxFq_nunjh!UEJPh$!Y&B9X2i}K2${oW>WbZWVnC?_oJo%(!hC>Kfei4lM+!EDwH+_ z_YWOa7c1%R1ThvDZ^MezPidce<{@2f|lZVl&%r;$GiOFw(hY#c2=00KB@do z%=Jr`S|I-A(`550-yYQ!-0NEwJb>lo3*o=Z6T$tyJ^i-!1G|Uqz7v7H7T+fkUXIz& zbA`iWZ8lYy4yYcB-;@Y1kL*!#R((&hYy7~%WdpZ&O&nMl{?Kx~LfHBTB8!)(^BIHF zdPW^@-xoe^34Exu_wDI7uUH;g0{^q5Gutzs+(I*6{oJEwt*8TFq6DnCO1KWHIejZ4 zOBUCuClg)cWH1}@n_?sJV@VlDtZoaQ&Q}ZvHPvM^VPy26W${W_L-dMi2 Kp{YT<^?w1RX`x%OIBH8VihoeI7zIY`mjX{nLfp;5 zD3WFpaqZvTKDItSb=&&6`}K*ft0SrINNBWcs#3dt*+OYrDZH~o10oF}OlH2{IrrXo z-pK_2?DqSf=X;a9?|aWV_uO;OJ@?#m?)y&W_UCHje-ibL8{4XvEL^!|{ibadcieF8 z$_KY>s}MrmwDOB$eM?i*#?8$O*0*k}@Gq@cy`{Bck>7u1;Z!mAy36TyaYgf{jTNhI zs9$AP-LSEBW8;>s8=JOO+_v$)uYmTpO%F2Xg?FsHzJl4K+_bTA<9*vUZm4M4ykTP# zv$>4A+` zY~I*xCD^`w`xTqFY<^&K%N0N`Y<=Lq`_U)nYOJg>o~knTH_xhyJw6!ytnHav5f!m# zR*G_?w<_uozw{a}R2jc&e)GHGWO0kjDEdt8_lJezxh{9=8&z@6uEh%c-96^^y` z4PuUke<9bWQU3q(Sa8|gCqDP|zm|)er$XaGeE0FcD=Gi>%g?0my}AC8+aJzC%w+`E z2m|q&>@d|3-+uY~T;sNE#9ScuP0Fg6+AvwgvRJ*JVUre0^(jPYe3w&wbb~|_3L;2kC{y;MT11#wdc-7;?8aF^Nf`s>)B>^ zIP*&KtFK;mOoj46sL4Jol&*YtLE#k7)S}{RnG(dp;dThS0}|RD1$466 zgv(J-jFU~B*Z_!B9^Rs2sSAIxx)D>=jki!k^3+W&ZXnKilqbZzPkCf_EmP9MO}u_e z_VY3vv+tPiJTZ?Y#tDL#lJMt)m(o##pHlGQJ6!m7a`^f9oDcpN;7@&k{G~7$L7l0Y zCramu8gy*lycz;i2}tfK!lpJa!r{srKqTA+O%mUB_)_+Wo2a*6&010 zm2>CLU9e!mqD70UtE(|C5ZNng%0KjpxHGvqP)E3vhtdROn`+WBP`I#5mTmkJyX0>r+AB}c)j#n?42^zJH_M8Mp&Se zBY3_~a!L=8XBYW)_c4zZz2o5@Jp9Uc9^SDdeK6g3EWM*Kl}fc&LnGDge64P;CP2Ga z0@|^N1Oiw-(&=M;pihfHXywXKK&1P=^U5pV=}Q;q7ys?Rz(89d6bc1=JA5^ZYyAGL zCx>>f$GZ5y(b#wH4jelcxcfWdq0!XnP*~WDR-{%G*}-*(&$lDsL$y#ygv8E+2mfZ~ z%$Z`v`s&8U>VY4IBAMp7@{i3?Dy7kaNt7vG5F`duf z(9q!b3H> z2ISR)?v@1_2U4C{A{iU?P`SDxHVU9unZ5 zTBde<)Zh00!-o&Y+Jqkrk^=)G849(BLP-oK^oH>qZNxY#;-2ljq}+V7=?!4FKpi{KEUO{DrC^DRPq zZD_Zlp-oWdJubUwBLnfZ!Ja{!InsXC4FTFb?HJdgh6eQi5S0gFXur$@FyK^9LQmC= z4d~KIlv_#TqeBgits%(k7hAdi9w8Ml)IbV2%21L^hyhXnuA|fg=0|!G;t(`W44L07 zlv_j0pAAoV{q0E6Y5b@f$$<;{4}*L!l_Fb(0=P?nLmrItKlnE!MVa3}17 z03=$eYjltz`k^Q4rO(qQ28i(vQKtI2qc7lE5vl>0^s++?sVn-zW#}V@nNbb8(2j-x z(XoC&$JYU+kM{m*h!8-1sh@r{o5J|B=_UuzUb3OBfu_bz&(49JVg<~7VBjrq!7u4Y zUx_iwfU}%nD6dpTzx#Xvax}6Vpo2Gv#o$V+8#kP6I7)WYmZTX8?T_`p-T!*gOkcp~ z8{CTia(}9oe5?R!w@mRL`wV}`*ZT=;P!*V^arJx$0*;8`slg@ z#|ZwYp%h;=e8fd?eE_S6rSMV%J3yi&M=%>BRV3{^u(VyrMcdcCB&DcC?}wh z?b2P1!V?`yrRCNABDvG*AbPqzsg7cG5R7n`cZc3Mgn89AFgh@b5ljxi@x`D%tOW4? z$$T*M!9h^Zk95vkD zUX9>vk^_o{UsJY#-cZP+4~l8{4*;L9y?5-umVkbIM&~4JhVHU=c2qENHruvBs4yJ4;xQU~?9WIwg+Mtxs z>=NJT4zVN@Y%mv`U=8@?gM$#X(ZD6}^q{I@gAzipLoq3fT$a%&QzkKj2uBc)(Gdvk zLofD)0$k$AjAJt@ra~N`A@a$TWSpYv9qtb;V;p$X3anayvG5^zQuHR{HzGw0hZu&U zF*+!cld&9?R6M7+AgW7ISf{Or*i&>z2loLrPjZR$+5g_*b`Ng`F%A)?Yyr3iOfWSn zJ9gY{k&LR*A+;p$8`Tt`(tGcv+8enAjtFV8atX?V*U+AbqC=}jC>K?-f@NDaVCNh>cxZ?@u3?knPkLtV*};e_W(X4K0iGx+5a&niqRkBjtno=hj5-L*-uuw#D zn$nu@L))XOC3zWTs6NRMUs6(PU_EqrFKH>b$Ds%mrG%M@02O7rfEy)?OipA$r!10* zPFy5Tr!NwxlNeo3abcuPU~tPwnbzQzWy!|r6i4$^J(5K;-H~n7NGNmBsgDGiJyP{_ z8YJtfq)E1(r3vU>)zEw-5n}Ajp(qqUXG`*`b0&FJBvzKKhXw~JhvK8XKiS`pT(}k` z_#n&;9Jr@LCRNhUr~2VIFp-pz$OMaKG#|7)V9ANel1#SbpzokepE3bPDNmR_4YUhr`nSg8^d?Q(Li4=BNQnLMNLy!(y|jZYaf*Nge?PDbX`m(5-Mh zZ&-)Doe$08qpmswd{}l$=o~Pu%0gtPfwXYQJz~W*I~Amr3p=jXWRO7G@kwivd&qRp zJTfVv%oj6BA@DjYRB0jBR%s4en=&&rQ$rzhLo+!fbxueRPht!Dx31!MW(vnCD&LkW9J7n`Z zmsDXB;_U{BP-n~&dVXn}5rVfZzrfK4JuBqvfZ4yHqQXX!od_n*; z9un{&Gg033x0cQHf#dDN{W=}xV3G4tnVRoW^i5uS$E#@yWbb*_Y0IRqD&T z#3pCH;bc*}v&^oNOn~tOB};zT9{QUZPs$Rr>;v@HGG&9-vY88K^dZwenGUP0Gs9oN z4OrVFe%3Oc31`^{6qi*ddTA2Ue)=;GjXH11j?oZ&tIm%z39=BIubH`H@X&U`XL4kj zBrADogp~cTyqU6;H&ZrqWz~Pea~7)gf%-&kX3XfVJS6{qh1Kn0?d!wr>(d*n=JZmD zvmj%V&qP>!xVQHELtEhFKIC#Hd*<|+6<{4N8gHxqNI};5Lgg&^%{&?d!;d9Qhs*6{ z=h8XZGUlD5 zV!-vYvu->PbeYkgYR@dQ920YIJcQQrsVixc4^>ucjfR?!1a&o)g+tf!FzI!DO~_X> zbDcCB&pblZ&1Glg^vKZU&m`GdIn_6_dxbaYSs!L@J~2BtcPdPJU0=(uL{izc(yn|o z$tc}FMJF$o{wjEOu8#cx&57%09%1TcRV-z4HTA8sZ}Xxk%yM?-e)42??v58NV?kgb-WHPNag7nt2(k%dpwEd+}=#?P5%nVD-TQ-`K!uVDLy~qqVU-a zsc{b{uG9SNC$xI}km>7GpW}CHvTr`S<>n^I_W?I2mJ*4d>GHkK`tfX+%h`E99`p`Q z$o#RKeq{2$cb}uDZ+P#1M~`!O@6R1Q_Tk>!7OgSPUR_t$r$0badDDhv73z~0SFE4k zT2XbyRaf(eM;7{*F087??XpFSmR-5HqP3}ID?TmKTycHd){4rhg<@8;Ry;n~>lNMk zbKXuz@_ToS9&cxU?^i`n11_DS=PWJ}(Q^wf8%0k+XMTBKUlbpH7<|ApE+>TEm7g<75KczT~XTwy;DTw&%gBc z-5&X4cW`>=kpD=$&)F56?mtp*c=PJ&a9g=EQ3;$s=BbGUrze)ndq3S*$@>brpEF-H zoebn}pXonxU?|deMfyjZ7B9E_RN+4HcKl^<_kw$O&`Yh=8}p~^+V6~i-JEA& zY_W%6k309QD_XN>op+6ixM=FG{jPY6vnqxr>Exl4mrh0Tbz1NTr`FZQ>zz@XsE?*a zeOIuE8!Tex+0ARts>{z!+qK^tF9rWkTXQSdJm}c7ZhA)CDj)Tu-;r+hb_G2wgzTYe z?vBsy+V774@Vxkna>922U&JhEShU2(gBKI>L2gkJn5h4}gixy;Q9JdX8kTzCVSRTF zA*-m-bgRdB@pB~OYzIV&|6XVovX*3O0CdLBh%DgJ zg#`RVHZaD(Ukb_7Sm`I4S3yHVq#K1?)S@v5*uwbJii2^XAH(`}T`Hu~qq;P{5T#b3 z4Q9_eHwi-2a{+9jpyGAB^D{bJLv z#FpN&bp6t{rSC1>gFpH6t)<^vnsBKq80H0VTbF!)$&za8&wEQwEm?3gjAm;3OXMY2 zbp@T3;m%-s*Zw~l>zD72HM`*~jLQS$E1i`)JA?2-P8hSX31i$DOmziQfpm*Aa{Nnu zxb+`-KJQ()$A|lVYwNz(6InNs11yTHJDmfZ9$9xP`c?R|T2XI|VR)UL!IRNW1&B+) ziD*Ot1|{HwuHXli?nh(AyRU}@WHsJ(!)M4X^gHT}3&|YF4;)g2s->^m@Id&dzR10tUU`vqj#LA@}MwG*%n+1QEbYYCmWjQT~q7Ew_b z=2#0p#ith1qOs+|R{Y2p(xf?iz}_+yHdRj}{P?9{5d95U9jL0ScZq{v35yOX zzTikWqQ7=Tg2$uNM18vTxbX&6&ghFkKOj&JgNvZ9&sf#UDr)Pa75Oye6ZogMml)@; z(7EHgQP&xmx~-CkK{z?>+eDkVo7P|+&mLO(c$A*NV$~TOj}`+%qxNmai17J&?IK=X z!Ers#8>oi#GtryCg}g!`V6JrQNc8gxFpU5?otP0_rSKnsDJmR~u2+B|0(1vY-&h}g zRDoz^2hFMIZUy)m0iZ)q1IeO2(&Ge;o&}9|N$m{L{^&-O;2f!n2HnF1ZdB<~tZyO+ zbQyhC0qQm2IR&WEfQpADca z18@2xP)50f3}%A+lH8oreu@}6>fnp~Q1ue;GwuAL>K&rIJ9sL-LMXWB8IKKN`ZGng z^2F5&R$_t8QLxz-*tA6P0=H;>Wr0gH4=k{Y=7Y3^Uf0S058eVB!mF1m5bQm+G zbH6`k54ys?7Li~w-I|OxD4i56puy34e`P+p+8I1+j_AJBFtr>r zd|g-26>x96lWe_W8)gIAsKtf7_Q;;lXmhEAb+1mHiNkjoH$tRD2~*T&fCQZggUqJY z)yVe8qJ`uy#*9uXGiS{GG0gq#1c*+N*e^>gxh9Fdi>qtZVC8fM@>_YiO}9$L92m;0 zSE@)M*mXtkSEZj&=!=PnI?ICN#k-@zoIB4EDiRzsCqf4Spa3iq=nU5XZYUx~8HHTq z{YSc2kDZB=P~EFX&%`}xtYoCJZ`4Nq<4oKhOk-di!Bcg0k>H5g_v>Ucr=vyGyVJ&F zRPGLrNX}q(n)**bau!7KWh!)mg8EO`yO@RS|Eg8MV<_3GF>O=ERA6aNaXgtaQuBCv zm?|=DWG@g-P;sR}MMV*psk(nq6o|}I#*0K@+T$sU(oJ`CJJELrKkN#A2w9E0FDIV| z%2PTT+OsZ&7(Ka$wN!7^Afm!}ow7zqa^`L}N2P>#Vg$@lIe9q%JSroYz1^!v&cqK4 zO;CL#cp8d}u2zG74prdfBylcjqHLlJG>F|d&%iPsJZ%nK7d1@w;gM$fE|oDL=D?BR zzDmF-{-Xn#_48Ed0);l*rzHT~>rIOc0!Blibn>}zYDL@j7-vajR2Tt`tju&K&k&__CZ@;vKEc@Md*QdH znG>8i+~A^k zcb#23DDBO#WhNJr2>DQoKpsHPacMxOak-0{mvi)*;K@CqQ!O`8`*Ol4$W@@>wFywn zzn6vWOgs-kGQztFVo<2-t%Ta+FVW6Hz*fBb5KNmqO7L`iA9jgO%L!s_u_<2)1|x+* zPiO-*xM@3j{%dhy2rD5dvieSqK1mx_iF+gmvz4rxlT`bJ%)bHVg`mY6jxYg^^P1r4 z;$4f<@n4~DC{o{gWjAH-fZzTX=v4pg>`u*tZ#g9XLY;aQ%&Aj1a;Gpt)TxfE(+J2W z=(p>J>FgG>l-_kiUc3dAu&CnQ5$ZhMgmFVw^-zvgJ&c*HNzR@Wtm1AR+uGtB|)c<{)~wb5P5CJhXwNQmgA1!3JsM`+sb zJiBYZCowk{Z{^CA-xvku1S{FLD^4nrHj-%MnUG^5A16YR80Uz9mZUvEYAvi+iC`Vm z)~@*Pa`$lZJA-iBOm)V2-#m2J!6OU!d|E;n7{KAIzNny0MB;fJNr)nMJD@VwkZ^G<^!u^hq5}fAFD< zrZMA@iDKp9L?vmibuY~VzX@yIiv;8G8p{pBkqyEwl+zk#AC8s%JR!FuI81pC#oZ9m z%8Z=+YHA1O&bdY-3a*4O7j#r8O89!0l*rA+C9`>Rv3Ci!O2-m~^NX5~%(piiiD6zx z$y#A|xv{XDV_{gHiiOctCPD;nFP7UeRV0P!yDp&;d`M*&88EVXpNv2~1Wpv;-=oQL z5)W)RB2CACs2l=BKwu%m&{5=ew92Ov53%!&^hLuW@*nSx%6L@f=pMJ^)kC~!zXrjz zaTyiZ7s))4_d#a|$05yyBvvuIHA#ChXk7^}XLS-%Oc1n)hyw9{D&Q`DWCsO2DANT& zQSl@7>Ai0`qVDtw_}UZb(20!7rFL1BFV`X{z{JnaAynQ9eL|76ONgZrOr$QAYXY>yWhT}0u6IdFL=`mX=eL4~bLN7iCu`ubmy_a) zbV*J=t}tKhs$emLmw{s$v14d|jaf&N!%uxV&w%}N#>}Ztt(ko0r0G2W?K5(uBy;0! zA30BQrMb?N_LYnmhPk~{m`xVvIc_@7zb1YYoaaLXW9JD6oq5J1cQC%p!Yk)V{lef+ zbe?EgM)=x!vfkyUp3Fs0rdtcstvJI+W;H@i^*$ek>j?}*7K(#DjQa#2;)XHyU=!eZ z3B(bUCvgZxu@u}1pJ4;IN3ZLRJH{xGxt~4zM-o1LjtH;*C|==l%4=sNO5oLh%xfV( zS$zoS=GW0S&CKp#Ay&`A<>_=Y(kqCA^s4xgm6MJ1(1lqe{l^&}Gt&Qd{G&(u3F0?l zr2md!=NswG|CNzWTrM>``N%Fpd$cQGi>Z7%ql=a||KE)ECJuEz!D#=4!?KSY?XSZi z{yU=`PK#z&IBjdL?Wk_-U+i)c@?p|HU`^awEQs-?VHa2%9o{N5DKyfeCHY1u_sD!D<9`ub8 zmKZ)yE@FsiRD?5+$N)x1H1TU7c1;Kt;@_Ag`Jlib2B{W*cr^C`4ZErAFT!96Du9{yh4s(<*%!=uA(Ef`tur+Lj=7!C=eUMdY`Bz zF8TEwA4o2|5_1G$<&i}K4mQm}YjFzvDn}dV5;J(-pLu6?@SI#)c&%39y6)Si3!vD< z=gr~19%U!3lsx2)pqmHUIuuK|hA%OLl7+wJWZ}R#xyd(iZhp~RzekLw3$WIj7CJbc z$6H(IZ>RmYEc5}JDe~8earbIBTc}G8>1m4f5gWQDS|~5~bQ((_074!>tC`0s!{6tL zlQy}zR6w{Zb%&t0gy~JCvo;YNjA1?CtjF2(QgeqQ`B>*I5O1b;jbIbS5SmH16qAGZ*U4Z;~eW{c<9p=pdLHquhq z4^72S+o-px_;Go~#KEAB$A1e4LmMz0_RxgHJw3uVF2RE#_nvh+y(PFYeR8>YOe^!z z+E3$qz;8ly!<$@>AVfl7^QnU|3VkMDpubkkN-D&Et-eG`PpdV$kkvc|X%7%({1=}h zNSnX}>%}LD&|WzC2_v-B2Ok@u9mY<=$F13ki|6MTKY9V%te4M=`25+_d`I!4#i{r< zN=rF#Yw_^tt5N5nz~*?%)|`&grq(=qg;SaWZ(kuVxKX_%!B6vnHO?Hv+i!`>&QFOv znUKa?M92-o4C(O@=5+8B0(|mH@=hilxaTc#wzOw|Pu7e_aPsBcHNE$XuKasCUtfc_ za=R`I9|`x~1b};}_wy*;Q{ER4E%wBHcooK;Xu*nQPi%)-IO5+E_{Zgr_|F9XZMh@< zA0kkI%a90oaks*`Fd*q-_xC=(2)$YBJV-~8L6q5 z?9$GBCC4#ccN(_}ga+t1?bf|-IMBVlzi_Or?;INLG={+h-Q@U>QFq^pZvMi-y~~_# zYSDq-gr1>aEmJFZ#*XE?M=3B&e5PKvSu(t~GTh>b9kYjz6)S~Ota$6**GY!8o%_+w z@s6STSY9JqUC|nW z5;aNh5$-EQlQKo*27WT3{QU{#uT!}@=tPo(i+(TenxL!rk?J(Rc6T>KG~el3PvkT$ z@iIQ%&^r;eJ5NNN`6uvh`w0qNop!m;<#L|LkT^hsKOz}GW?+jA**%4w`+F$Z1q$0@ zdEOI!Rlhp(p?uFK^SJ-X0%|UpiWbo0vXpUz%6O1lTW|Cgkmk;C21n1^&QwAzQ|Ltx zhMvK)Aqjh^4#?mEyzIT`U8E}x0hsV{?Y!|c>SLYBOQ!3M62fq?-h5T31}t3B=~9M< zj0`o9fyQE#_>z2e8Qdi-ANGJoDr@CF4jLJ$wBtTs?djC=zMb6N{oGpbz5Td9O zn_pbUHj_$p@ahVTC{f36>60vDa%Yu7W4xP=S3oJP!n0v+nLbE>V2Zbrlbq=6%;(2p zV=yB!%xi*$O)nVZ^oCEs+k|+XY8V%%5V7jFDn^Z7pj{JWLlk&E*{&s__+81%-{I#Q zC})JCH+j0(jXvDBq+|_V`GR;-u%oUl!SI%8(@Vw%C0GH~GP=gI#H##sVqHUG@YXC8 zWfcgo*hzsrSpwajE6^*(yBJQ=R6!KAjI&885M0)NN9Um)#|bzs>356{P<{%fv2;$_ zIG!M#S4%fLOS+fxa@6&Tag`|@Y8m$^>F5)~{ATtl<12`+VQ9|yb+%}`ph&^^Js3GL z3jDAkje;w>Ltdai!p{f!reZV5Gq{ywxfbSRVxCH~#?O&d{F z#>mJ_QpPulleuGhqlv^v4pPQ;LQ*5M=+)K72mOD-hnu>J!@n=?U5^hx^*Y4z7aT42 zmuzeC`KDQGZtdJBKN*Dw)bueZ#9d>y=F+CmhR5v9_Qbr(ogQ!a$jR_PK}$*H7Ijxx zdBPLsdpABZ#UG#Qyev9>`rQc9m}U46w%8vW8OD`o-0yVeD+;vPhe#p(q3xabd9fHr zB(%>l%xJTI_>}FPKUg@7TR7-8Kx3guSt!_Q@ir&D1h;417#`hm#JOY;%E7~CWOCE7 zV~tlxy0Iy)p5S2vl%GOlQ#2*xR=TqXi}-<83d&VnPQHiXNZgFiY`_&xzY*5yHTKy7 z!>gZ|A(eI{Nu^oXf0S4^c1qx!<$f;-g!e+pX?_=}g4?qF_ygjC_eEQZ;o?-Ie?yJZ zxCTTsUI%ZUp$E7Z4}bGJ`~2y(okLK6{TfzDWDxMq{CgM(ztVfD2cOt+(@ZjMvqz4T zp`u({%aD}>nT1CJH{lO2JOh*G6pV`4fTCw~>a}G;&6cRmgwk&qzlH+(Lg+aX{qKOl zO%UW#3F)H>& zqEodh3A#2zv`9i05)s}bRFW>1(3|+Fsdj!nX(ZK@Tcs1oLJ_dZ{l~7a{?@iE=xo6o zR78-#`$+n+V4$S+Jw$nGC9J>2btm?rcAXW?Uc_OK$FQRk!4|wb`QdZ-=HIoJ-#wn3 z2(l+X{HH9US$A}=_7JZNGrU0d_#iAO(x3eBAJ>(CD*7K-=-135o`c=%TwVF)_pn?U zP`3uvXJF_AJ}G&R>Ouw%fg&dS*6ur;$M0rtbo(cHTTl0}Zba@<0aS)&uo8Z$@3D8} zYIuClIwwBKV+^OULr(!rlB1Zo6I&4Jz#P1Kj;%utq+P2deRS$=Yy+eN{wBPXk`7$G z9lJ^xw7hrHFa^XH@*^JfqSSxV_S#tdDJE|#-u*4ny>8^X>(C%}fUqNBq*65ND3u-C z9cytRkOe)b0D$1h$w|IX+|nI9Nn9zaI>ozLc&Ho+4tEEKmlufb7vP%b#~c!Q^@bCB zF3!X>0xeab52zKeAcoceeXQw6+~tIqJ0R=tXX15ENQpf@CrxCdj$klPdK7t-tq$L) z^CZ5`s+PVe=xP3ht_a)1_}VSE*XDLQ&9BRms3A=uulj5Q4_6M4A?5-9Fh$exbx4-N z_AIEd+sY@%u>o&ruC=?p_`)pu9-&E&4HICFoW4{zBoCY0?F4)4F(eBW6L{z4@DNV? zI7lBJT&*mG;sJct;mzfdM_;uC9>q47$P;;m_?8xY$cbtVsjB!|ue?Hhdy4{Jki(lvEspfv4Ahk;bHcLc%Uy9Vl4;t#R8t5!y}xp#>K~SxbgibsKbZi5r)-R z!KFDo8Vc075D!}xvEtECkj=xF!$Ww~xDbzQV#Na#S*%y)@+ee&sj$f5_R&1kJPI`r zH~%M$>vDL6J*qF~Y`I2Ynlz)T!hV1dnY0QEQ{Go})QuJI|b} zrLPgQ9Qyy`TR@-smcNE_q5MwD3VdIr`8|{B%OAJh*LvUP&G&7xe!=6`rY&FIxW0Lt z{-(!;B8y9%`Gu6(aQZgNYd74twRvNckpHgW{*CHi6WynhBgbhe zdK>pw;hvXs{%{^)FR@@RG_m~J7qEF2?AbF^m)pflRMc+g{@8KHv-!>T)P9Jt##kUC zeN*kiC>11)BC3xJ8cwnH9xWtxo0O2u3Po!d@QRidi=xCnd`{S!rxzS-DZ4eAN9-lp zo2o!Wk$rDQZ??Uubm7isgrc>Xf@~~`R;()@$k8Hy5%Q`D=0^l$wKeT zNFnGoFXV60SdTG1W!O^7V?8Z1G6X#~WE17lz8>TBcyHIXHO9U8kVT*Ivot=YJq1As z{!d2jws_)a@;0NGYkx;j$hfje4!T^;H1z{(bHSBFRiu15^s zVM_%THCHHnIpeQyxsdT|T8bHeZA(7IiyfomJ$H11QP1_AVAHdv6HI!p?F0)n8|kp) z0%2XL-fuQVo^qzp_YOBD038K6J)r|qDrBUbx7%#oxOq66OxX^8P zIorpxxeR6zgXqoZ(b#zUMf}NO%O|j!@)%qChXX0RWxL`uqVk9LCrL+hMD21>+v4o8 zCG7qf0^^QR2B$%b(H%>zNxwLX{Muzq#Vbot=@>LPmVyS?s!xdTc`6B_)}- z<;o`b>95=PI`M+haW9j`#n5%8mqx>f;DYUi$vQ{7aHEjj*;7m1?Ziv_q=N8r5rzuF z5_X1Q+<)9)!*bgtt5(sL+VXSsp;)}FCwGYJjbpE3XP$({jvQ@d$Sqmp2;TO=h8*p~ zQoi$5L6rq6cdr|xA++0C3Zh>Y^~R4-A251Cx@t__&M@wkw`?@^#uk*Q{$X6P$?mZg z@@F889+WXE(YvFzJ$jguOYgYI|R}t798WIY~>)4 zvftr73WzbsCYlR+_hMrz($`YJ&--XA0~N756+S0gD(RJ^8BIuYY<-b;jBCb>8^^AG z2md0n@aLRp=H^S#^%`?O2?9HyGX+(~f4bS@1o$puuYVDa1jgB$n2V68B z8;iVl=KV;Y@ikRFd@kHPg=&|mcHS_`#?aVRW86vw=#8sE%W^>~Tk|YQXgqZ`oOU%A zhSTnrnNur7i(}63(#At)Uve3bo}E)6n(Z&SwS0Yj>K_+j9pA96V$;T^jpEJ!15tq~ AzyJUM literal 0 HcmV?d00001 diff --git a/tools/ioemu/qemu-binfmt-conf.sh b/tools/ioemu/qemu-binfmt-conf.sh new file mode 100644 index 0000000000..e5acc474aa --- /dev/null +++ b/tools/ioemu/qemu-binfmt-conf.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# enable automatic i386/ARM/SPARC/PPC program execution by the kernel + +# load the binfmt_misc module +/sbin/modprobe binfmt_misc + +# probe cpu type +cpu=`uname -m` +case "$cpu" in + i386|i486|i586|i686|i86pc|BePC) + cpu="i386" + ;; + "Power Macintosh"|ppc|ppc64) + cpu="ppc" + ;; + armv4l) + cpu="arm" + ;; +esac + +# register the interpreter for each cpu except for the native one +if [ $cpu != "i386" ] ; then + echo ':i386:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff:/usr/local/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register + echo ':i486:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff:/usr/local/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register +fi +if [ $cpu != "arm" ] ; then + echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff:/usr/local/bin/qemu-arm:' > /proc/sys/fs/binfmt_misc/register +fi +if [ $cpu != "sparc" ] ; then + echo ':sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff:/usr/local/bin/qemu-sparc:' > /proc/sys/fs/binfmt_misc/register +fi +if [ $cpu != "ppc" ] ; then + echo ':ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff:/usr/local/bin/qemu-ppc:' > /proc/sys/fs/binfmt_misc/register +fi diff --git a/tools/ioemu/qemu-doc.html b/tools/ioemu/qemu-doc.html new file mode 100644 index 0000000000..2192530827 --- /dev/null +++ b/tools/ioemu/qemu-doc.html @@ -0,0 +1,1793 @@ + + + + +QEMU CPU Emulator User Documentation + + +

QEMU CPU Emulator User Documentation

+

+


+

Table of Contents

+
+


+ +

+QEMU CPU Emulator User Documentation + + + + +

1. Introduction

+ + + +

1.1 Features

+ +

+QEMU is a FAST! processor emulator using dynamic translation to +achieve good emulation speed. + + +

+QEMU has two operating modes: + + + +

    + +
  • + +Full system emulation. In this mode, QEMU emulates a full system (for +example a PC), including a processor and various peripherials. It can +be used to launch different Operating Systems without rebooting the +PC or to debug system code. + +
  • + +User mode emulation (Linux host only). In this mode, QEMU can launch +Linux processes compiled for one CPU on another CPU. It can be used to +launch the Wine Windows API emulator (http://www.winehq.org) or +to ease cross-compilation and cross-debugging. + +
+ +

+As QEMU requires no host kernel driver to run, it is very safe and +easy to use. + + +

+For system emulation, the following hardware targets are supported: + +

    +
  • PC (x86 processor) + +
  • PREP (PowerPC processor) + +
  • PowerMac (PowerPC processor, in progress) + +
+ +

+For user emulation, x86, PowerPC, ARM, and SPARC CPUs are supported. + + + + +

2. Installation

+ +

+If you want to compile QEMU yourself, see section 6. Compilation from the sources. + + + + +

2.1 Linux

+ +

+Download the binary distribution (`qemu-XXX-i386.tar.gz') and +untar it as root in `/': + + + +

+su
+cd /
+tar zxvf /tmp/qemu-XXX-i386.tar.gz
+
+ + + +

2.2 Windows

+ +

+Download the experimental binary installer at +http://www.freeoszoo.org/download.php. + + + + +

2.3 Mac OS X

+ +

+Download the experimental binary installer at +http://www.freeoszoo.org/download.php. + + + + +

3. QEMU PC System emulator invocation

+ + + +

3.1 Introduction

+ +

+The QEMU System emulator simulates a complete PC. + + +

+In order to meet specific user needs, two versions of QEMU are +available: + + + +

    + +
  1. + +qemu-fast uses the host Memory Management Unit (MMU) to +simulate the x86 MMU. It is fast but has limitations because +the whole 4 GB address space cannot be used and some memory mapped +peripherials cannot be emulated accurately yet. Therefore, a specific +guest Linux kernel can be used (See section 3.9 Linux Kernel Compilation) as guest +OS. + +Moreover there is no separation between the host and target address +spaces, so it offers no security (the target OS can modify the +qemu-fast code by writing at the right addresses). + +
  2. + +qemu uses a software MMU. It is about two times slower +but gives a more accurate emulation and a complete separation between +the host and target address spaces. + +
+ +

+QEMU emulates the following PC peripherials: + + + +

    +
  • + +i440FX host PCI bridge and PIIX3 PCI to ISA bridge +
  • + +Cirrus CLGD 5446 PCI VGA card or dummy VGA card with Bochs VESA +extensions (hardware level, including all non standard modes). +
  • + +PS/2 mouse and keyboard +
  • + +2 PCI IDE interfaces with hard disk and CD-ROM support +
  • + +Floppy disk +
  • + +NE2000 PCI network adapters +
  • + +Serial ports +
  • + +Soundblaster 16 card +
+ +

+QEMU uses the PC BIOS from the Bochs project and the Plex86/Bochs LGPL +VGA BIOS. + + + + +

3.2 Quick Start

+ +

+Download and uncompress the linux image (`linux.img') and type: + + + +

+qemu linux.img
+
+ +

+Linux should boot and give you a prompt. + + + + +

3.3 Invocation

+ + +
+usage: qemu [options] [disk_image]
+
+ +

+disk_image is a raw hard disk image for IDE hard disk 0. + + +

+General options: +

+ +
@option{-fda file} +
+
@option{-fdb file} +
+Use file as floppy disk 0/1 image (See section 3.6 Disk Images). You can +use the host floppy by using `/dev/fd0' as filename. + +
@option{-hda file} +
+
@option{-hdb file} +
+
@option{-hdc file} +
+
@option{-hdd file} +
+Use file as hard disk 0, 1, 2 or 3 image (See section 3.6 Disk Images). + +
@option{-cdrom file} +
+Use file as CD-ROM image (you cannot use @option{-hdc} and and +@option{-cdrom} at the same time). You can use the host CD-ROM by +using `/dev/cdrom' as filename. + +
@option{-boot [a|c|d]} +
+Boot on floppy (a), hard disk (c) or CD-ROM (d). Hard disk boot is +the default. + +
@option{-snapshot} +
+Write to temporary files instead of disk image files. In this case, +the raw disk image you use is not written back. You can however force +the write back by pressing C-a s (See section 3.6 Disk Images). + +
@option{-m megs} +
+Set virtual RAM size to megs megabytes. Default is 128 MB. + +
@option{-nographic} +
+Normally, QEMU uses SDL to display the VGA output. With this option, +you can totally disable graphical output so that QEMU is a simple +command line application. The emulated serial port is redirected on +the console. Therefore, you can still use QEMU to debug a Linux kernel +with a serial console. + +
@option{-enable-audio} +
+The SB16 emulation is disabled by default as it may give problems with +Windows. You can enable it manually with this option. + +
@option{-localtime} +
+Set the real time clock to local time (the default is to UTC +time). This option is needed to have correct date in MS-DOS or +Windows. + +
@option{-full-screen} +
+Start in full screen. + +
+ +

+Network options: + + +

+ +
@option{-n script} +
+Set TUN/TAP network init script [default=/etc/qemu-ifup]. This script +is launched to configure the host network interface (usually tun0) +corresponding to the virtual NE2000 card. + +
@option{-macaddr addr} +
+Set the mac address of the first interface (the format is +aa:bb:cc:dd:ee:ff in hexa). The mac address is incremented for each +new network interface. + +
@option{-tun-fd fd} +
+Assumes fd talks to a tap/tun host network interface and use +it. Read http://bellard.org/qemu/tetrinet.html to have an +example of its use. + +
@option{-user-net} +
+Use the user mode network stack. This is the default if no tun/tap +network init script is found. + +
@option{-tftp prefix} +
+When using the user mode network stack, activate a built-in TFTP +server. All filenames beginning with prefix can be downloaded +from the host to the guest using a TFTP client. The TFTP client on the +guest must be configured in binary mode (use the command bin of +the Unix TFTP client). The host IP address on the guest is as usual +10.0.2.2. + +
@option{-smb dir} +
+When using the user mode network stack, activate a built-in SMB +server so that Windows OSes can access to the host files in `dir' +transparently. + +In the guest Windows OS, the line: + +
+10.0.2.4 smbserver
+
+ +must be added in the file `C:\WINDOWS\LMHOSTS' (for windows 9x/Me) +or `C:\WINNT\SYSTEM32\DRIVERS\ETC\LMHOSTS' (Windows NT/2000). + +Then `dir' can be accessed in `\\smbserver\qemu'. + +Note that a SAMBA server must be installed on the host OS in +`/usr/sbin/smbd'. QEMU was tested succesfully with smbd version +2.2.7a from the Red Hat 9. + +
@option{-redir [tcp|udp]:host-port:[guest-host]:guest-port} +
+When using the user mode network stack, redirect incoming TCP or UDP +connections to the host port host-port to the guest +guest-host on guest port guest-port. If guest-host +is not specified, its value is 10.0.2.15 (default address given by the +built-in DHCP server). + +For example, to redirect host X11 connection from screen 1 to guest +screen 0, use the following: + + +
+# on the host
+qemu -redir tcp:6001::6000 [...]
+# this host xterm should open in the guest X11 server
+xterm -display :1
+
+ +To redirect telnet connections from host port 5555 to telnet port on +the guest, use the following: + + +
+# on the host
+qemu -redir tcp:5555::23 [...]
+telnet localhost 5555
+
+ +Then when you use on the host telnet localhost 5555, you +connect to the guest telnet server. + +
@option{-dummy-net} +
+Use the dummy network stack: no packet will be received by the network +cards. + +
+ +

+Linux boot specific. When using this options, you can use a given +Linux kernel without installing it in the disk image. It can be useful +for easier testing of various kernels. + + +

+ +
@option{-kernel bzImage} +
+Use bzImage as kernel image. + +
@option{-append cmdline} +
+Use cmdline as kernel command line + +
@option{-initrd file} +
+Use file as initial ram disk. + +
+ +

+Debug/Expert options: +

+ +
@option{-serial dev} +
+Redirect the virtual serial port to host device dev. Available +devices are: +
+ +
vc +
+Virtual console +
pty +
+[Linux only] Pseudo TTY (a new PTY is automatically allocated) +
null +
+void device +
stdio +
+[Unix only] standard input/output +
+The default device is vc in graphical mode and stdio in +non graphical mode. + +This option can be used several times to simulate up to 4 serials +ports. + +
@option{-monitor dev} +
+Redirect the monitor to host device dev (same devices as the +serial port). +The default device is vc in graphical mode and stdio in +non graphical mode. + +
@option{-s} +
+Wait gdb connection to port 1234 (See section 3.10 GDB usage). +
@option{-p port} +
+Change gdb connection port. +
@option{-S} +
+Do not start CPU at startup (you must type 'c' in the monitor). +
@option{-d} +
+Output log in /tmp/qemu.log +
@option{-isa} +
+Simulate an ISA-only system (default is PCI system). +
@option{-std-vga} +
+Simulate a standard VGA card with Bochs VBE extensions (default is +Cirrus Logic GD5446 PCI VGA) +
@option{-loadvm file} +
+Start right away with a saved state (loadvm in monitor) +
+ + + +

3.4 Keys

+ +

+During the graphical emulation, you can use the following keys: +

+ +
Ctrl-Alt-f +
+Toggle full screen + +
Ctrl-Alt-n +
+Switch to virtual console 'n'. Standard console mappings are: +
+ +
1 +
+Target system display +
2 +
+Monitor +
3 +
+Serial port +
+ +
Ctrl-Alt +
+Toggle mouse and keyboard grab. +
+ +

+In the virtual consoles, you can use Ctrl-Up, Ctrl-Down, +Ctrl-PageUp and Ctrl-PageDown to move in the back log. + + +

+During emulation, if you are using the @option{-nographic} option, use +Ctrl-a h to get terminal commands: + + +

+ +
Ctrl-a h +
+Print this help +
Ctrl-a x +
+Exit emulatior +
Ctrl-a s +
+Save disk data back to file (if -snapshot) +
Ctrl-a b +
+Send break (magic sysrq in Linux) +
Ctrl-a c +
+Switch between console and monitor +
Ctrl-a Ctrl-a +
+Send Ctrl-a +
+ + + +

3.5 QEMU Monitor

+ +

+The QEMU monitor is used to give complex commands to the QEMU +emulator. You can use it to: + + + +

    + +
  • + +Remove or insert removable medias images +(such as CD-ROM or floppies) + +
  • + +Freeze/unfreeze the Virtual Machine (VM) and save or restore its state +from a disk file. + +
  • Inspect the VM state without an external debugger. + +
+ + + +

3.5.1 Commands

+ +

+The following commands are available: + + +

+ +
@option{help or ? [cmd]} +
+Show the help for all commands or just for command cmd. + +
@option{commit} +
+Commit changes to the disk images (if -snapshot is used) + +
@option{info subcommand} +
+show various information about the system state + +
+ +
@option{info network} +
+show the network state +
@option{info block} +
+show the block devices +
@option{info registers} +
+show the cpu registers +
@option{info history} +
+show the command line history +
+ +
@option{q or quit} +
+Quit the emulator. + +
@option{eject [-f] device} +
+Eject a removable media (use -f to force it). + +
@option{change device filename} +
+Change a removable media. + +
@option{screendump filename} +
+Save screen into PPM image filename. + +
@option{log item1[,...]} +
+Activate logging of the specified items to `/tmp/qemu.log'. + +
@option{savevm filename} +
+Save the whole virtual machine state to filename. + +
@option{loadvm filename} +
+Restore the whole virtual machine state from filename. + +
@option{stop} +
+Stop emulation. + +
@option{c or cont} +
+Resume emulation. + +
@option{gdbserver [port]} +
+Start gdbserver session (default port=1234) + +
@option{x/fmt addr} +
+Virtual memory dump starting at addr. + +
@option{xp /fmt addr} +
+Physical memory dump starting at addr. + +fmt is a format which tells the command how to format the +data. Its syntax is: @option{/{count}{format}{size}} + +
+ +
count +
+is the number of items to be dumped. + +
format +
+can be x (hexa), d (signed decimal), u (unsigned decimal), o (octal), +c (char) or i (asm instruction). + +
size +
+can be b (8 bits), h (16 bits), w (32 bits) or g (64 bits). On x86, +h or w can be specified with the i format to +respectively select 16 or 32 bit code instruction size. + +
+ +Examples: + +
    +
  • + +Dump 10 instructions at the current instruction pointer: + +
    +(qemu) x/10i $eip
    +0x90107063:  ret
    +0x90107064:  sti
    +0x90107065:  lea    0x0(%esi,1),%esi
    +0x90107069:  lea    0x0(%edi,1),%edi
    +0x90107070:  ret
    +0x90107071:  jmp    0x90107080
    +0x90107073:  nop
    +0x90107074:  nop
    +0x90107075:  nop
    +0x90107076:  nop
    +
    + +
  • + +Dump 80 16 bit values at the start of the video memory. + +
    +(qemu) xp/80hx 0xb8000
    +0x000b8000: 0x0b50 0x0b6c 0x0b65 0x0b78 0x0b38 0x0b36 0x0b2f 0x0b42
    +0x000b8010: 0x0b6f 0x0b63 0x0b68 0x0b73 0x0b20 0x0b56 0x0b47 0x0b41
    +0x000b8020: 0x0b42 0x0b69 0x0b6f 0x0b73 0x0b20 0x0b63 0x0b75 0x0b72
    +0x000b8030: 0x0b72 0x0b65 0x0b6e 0x0b74 0x0b2d 0x0b63 0x0b76 0x0b73
    +0x000b8040: 0x0b20 0x0b30 0x0b35 0x0b20 0x0b4e 0x0b6f 0x0b76 0x0b20
    +0x000b8050: 0x0b32 0x0b30 0x0b30 0x0b33 0x0720 0x0720 0x0720 0x0720
    +0x000b8060: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
    +0x000b8070: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
    +0x000b8080: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
    +0x000b8090: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
    +
    + +
+ +
@option{p or print/fmt expr} +
+Print expression value. Only the format part of fmt is +used. + +
@option{sendkey keys} +
+Send keys to the emulator. Use - to press several keys +simultaneously. Example: + +
+sendkey ctrl-alt-f1
+
+ +This command is useful to send keys that your graphical user interface +intercepts at low level, such as ctrl-alt-f1 in X Window. + +
@option{system_reset} +
+Reset the system. + +
+ + + +

3.5.2 Integer expressions

+ +

+The monitor understands integers expressions for every integer +argument. You can use register names to get the value of specifics +CPU registers by prefixing them with $. + + + + +

3.6 Disk Images

+ + + +

3.6.1 Raw disk images

+ +

+The disk images can simply be raw images of the hard disk. You can +create them with the command: + +

+dd of=myimage bs=1024 seek=mysize count=0
+
+ +

+where myimage is the image filename and mysize is its size +in kilobytes. + + + + +

3.6.2 Snapshot mode

+ +

+If you use the option @option{-snapshot}, all disk images are +considered as read only. When sectors in written, they are written in +a temporary file created in `/tmp'. You can however force the +write back to the raw disk images by pressing C-a s. + + +

+NOTE: The snapshot mode only works with raw disk images. + + + + +

3.6.3 Copy On Write disk images

+ +

+QEMU also supports user mode Linux +(http://user-mode-linux.sourceforge.net/) Copy On Write (COW) +disk images. The COW disk images are much smaller than normal images +as they store only modified sectors. They also permit the use of the +same disk image template for many users. + + +

+To create a COW disk images, use the command: + + + +

+qemu-mkcow -f myrawimage.bin mycowimage.cow
+
+ +

+`myrawimage.bin' is a raw image you want to use as original disk +image. It will never be written to. + + +

+`mycowimage.cow' is the COW disk image which is created by +qemu-mkcow. You can use it directly with the @option{-hdx} +options. You must not modify the original raw disk image if you use +COW images, as COW images only store the modified sectors from the raw +disk image. QEMU stores the original raw disk image name and its +modified time in the COW disk image so that chances of mistakes are +reduced. + + +

+If the raw disk image is not read-only, by pressing C-a s you +can flush the COW disk image back into the raw disk image, as in +snapshot mode. + + +

+COW disk images can also be created without a corresponding raw disk +image. It is useful to have a big initial virtual disk image without +using much disk space. Use: + + + +

+qemu-mkcow mycowimage.cow 1024
+
+ +

+to create a 1 gigabyte empty COW disk image. + + +

+NOTES: + +

    +
  1. + +COW disk images must be created on file systems supporting +holes such as ext2 or ext3. +
  2. + +Since holes are used, the displayed size of the COW disk image is not +the real one. To know it, use the ls -ls command. +
+ + + +

3.6.4 Convert VMware disk images to raw disk images

+ +

+You can use the tool `vmdk2raw' to convert VMware disk images to +raw disk images directly usable by QEMU. The syntax is: + +

+vmdk2raw vmware_image output_image
+
+ + + +

3.7 Network emulation

+ +

+QEMU simulates up to 6 networks cards (NE2000 boards). Each card can +be connected to a specific host network interface. + + + + +

3.7.1 Using tun/tap network interface

+ +

+This is the standard way to emulate network. QEMU adds a virtual +network device on your host (called tun0), and you can then +configure it as if it was a real ethernet card. + + +

+As an example, you can download the `linux-test-xxx.tar.gz' +archive and copy the script `qemu-ifup' in `/etc' and +configure properly sudo so that the command ifconfig +contained in `qemu-ifup' can be executed as root. You must verify +that your host kernel supports the TUN/TAP network interfaces: the +device `/dev/net/tun' must be present. + + +

+See section 3.8 Direct Linux Boot to have an example of network use with a +Linux distribution. + + + + +

3.7.2 Using the user mode network stack

+ +

+By using the option @option{-user-net} or if you have no tun/tap init +script, QEMU uses a completely user mode network stack (you don't need +root priviledge to use the virtual network). The virtual network +configuration is the following: + + + +

+
+QEMU Virtual Machine    <------>  Firewall/DHCP server <-----> Internet
+     (10.0.2.x)            |          (10.0.2.2)
+                           |
+                           ---->  DNS server (10.0.2.3)
+                           |     
+                           ---->  SMB server (10.0.2.4)
+
+ +

+The QEMU VM behaves as if it was behind a firewall which blocks all +incoming connections. You can use a DHCP client to automatically +configure the network in the QEMU VM. + + +

+In order to check that the user mode network is working, you can ping +the address 10.0.2.2 and verify that you got an address in the range +10.0.2.x from the QEMU virtual DHCP server. + + +

+Note that ping is not supported reliably to the internet as it +would require root priviledges. It means you can only ping the local +router (10.0.2.2). + + +

+When using the built-in TFTP server, the router is also the TFTP +server. + + +

+When using the @option{-redir} option, TCP or UDP connections can be +redirected from the host to the guest. It allows for example to +redirect X11, telnet or SSH connections. + + + + +

3.8 Direct Linux Boot

+ +

+This section explains how to launch a Linux kernel inside QEMU without +having to make a full bootable image. It is very useful for fast Linux +kernel testing. The QEMU network configuration is also explained. + + + +

    +
  1. + +Download the archive `linux-test-xxx.tar.gz' containing a Linux +kernel and a disk image. + +
  2. Optional: If you want network support (for example to launch X11 examples), you + +must copy the script `qemu-ifup' in `/etc' and configure +properly sudo so that the command ifconfig contained in +`qemu-ifup' can be executed as root. You must verify that your host +kernel supports the TUN/TAP network interfaces: the device +`/dev/net/tun' must be present. + +When network is enabled, there is a virtual network connection between +the host kernel and the emulated kernel. The emulated kernel is seen +from the host kernel at IP address 172.20.0.2 and the host kernel is +seen from the emulated kernel at IP address 172.20.0.1. + +
  3. Launch qemu.sh. You should have the following output: + + +
    +> ./qemu.sh 
    +Connected to host network interface: tun0
    +Linux version 2.4.21 (bellard@voyager.localdomain) (gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) #5 Tue Nov 11 18:18:53 CET 2003
    +BIOS-provided physical RAM map:
    + BIOS-e801: 0000000000000000 - 000000000009f000 (usable)
    + BIOS-e801: 0000000000100000 - 0000000002000000 (usable)
    +32MB LOWMEM available.
    +On node 0 totalpages: 8192
    +zone(0): 4096 pages.
    +zone(1): 4096 pages.
    +zone(2): 0 pages.
    +Kernel command line: root=/dev/hda sb=0x220,5,1,5 ide2=noprobe ide3=noprobe ide4=noprobe ide5=noprobe console=ttyS0
    +ide_setup: ide2=noprobe
    +ide_setup: ide3=noprobe
    +ide_setup: ide4=noprobe
    +ide_setup: ide5=noprobe
    +Initializing CPU#0
    +Detected 2399.621 MHz processor.
    +Console: colour EGA 80x25
    +Calibrating delay loop... 4744.80 BogoMIPS
    +Memory: 28872k/32768k available (1210k kernel code, 3508k reserved, 266k data, 64k init, 0k highmem)
    +Dentry cache hash table entries: 4096 (order: 3, 32768 bytes)
    +Inode cache hash table entries: 2048 (order: 2, 16384 bytes)
    +Mount cache hash table entries: 512 (order: 0, 4096 bytes)
    +Buffer-cache hash table entries: 1024 (order: 0, 4096 bytes)
    +Page-cache hash table entries: 8192 (order: 3, 32768 bytes)
    +CPU: Intel Pentium Pro stepping 03
    +Checking 'hlt' instruction... OK.
    +POSIX conformance testing by UNIFIX
    +Linux NET4.0 for Linux 2.4
    +Based upon Swansea University Computer Society NET3.039
    +Initializing RT netlink socket
    +apm: BIOS not found.
    +Starting kswapd
    +Journalled Block Device driver loaded
    +Detected PS/2 Mouse Port.
    +pty: 256 Unix98 ptys configured
    +Serial driver version 5.05c (2001-07-08) with no serial options enabled
    +ttyS00 at 0x03f8 (irq = 4) is a 16450
    +ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)
    +Last modified Nov 1, 2000 by Paul Gortmaker
    +NE*000 ethercard probe at 0x300: 52 54 00 12 34 56
    +eth0: NE2000 found at 0x300, using IRQ 9.
    +RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
    +Uniform Multi-Platform E-IDE driver Revision: 7.00beta4-2.4
    +ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xx
    +hda: QEMU HARDDISK, ATA DISK drive
    +ide0 at 0x1f0-0x1f7,0x3f6 on irq 14
    +hda: attached ide-disk driver.
    +hda: 20480 sectors (10 MB) w/256KiB Cache, CHS=20/16/63
    +Partition check:
    + hda:
    +Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996
    +NET4: Linux TCP/IP 1.0 for NET4.0
    +IP Protocols: ICMP, UDP, TCP, IGMP
    +IP: routing cache hash table of 512 buckets, 4Kbytes
    +TCP: Hash tables configured (established 2048 bind 4096)
    +NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
    +EXT2-fs warning: mounting unchecked fs, running e2fsck is recommended
    +VFS: Mounted root (ext2 filesystem).
    +Freeing unused kernel memory: 64k freed
    + 
    +Linux version 2.4.21 (bellard@voyager.localdomain) (gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) #5 Tue Nov 11 18:18:53 CET 2003
    + 
    +QEMU Linux test distribution (based on Redhat 9)
    + 
    +Type 'exit' to halt the system
    + 
    +sh-2.05b# 
    +
    + +
  4. + +Then you can play with the kernel inside the virtual serial console. You +can launch ls for example. Type Ctrl-a h to have an help +about the keys you can type inside the virtual serial console. In +particular, use Ctrl-a x to exit QEMU and use Ctrl-a b as +the Magic SysRq key. + +
  5. + +If the network is enabled, launch the script `/etc/linuxrc' in the +emulator (don't forget the leading dot): + +
    +. /etc/linuxrc
    +
    + +Then enable X11 connections on your PC from the emulated Linux: + +
    +xhost +172.20.0.2
    +
    + +You can now launch `xterm' or `xlogo' and verify that you have +a real Virtual Linux system ! + +
+ +

+NOTES: + +

    +
  1. + +A 2.5.74 kernel is also included in the archive. Just +replace the bzImage in qemu.sh to try it. + +
  2. + +qemu-fast creates a temporary file in $QEMU_TMPDIR (`/tmp' is the +default) containing all the simulated PC memory. If possible, try to use +a temporary directory using the tmpfs filesystem to avoid too many +unnecessary disk accesses. + +
  3. + +In order to exit cleanly from qemu, you can do a shutdown inside +qemu. qemu will automatically exit when the Linux shutdown is done. + +
  4. + +You can boot slightly faster by disabling the probe of non present IDE +interfaces. To do so, add the following options on the kernel command +line: + +
    +ide1=noprobe ide2=noprobe ide3=noprobe ide4=noprobe ide5=noprobe
    +
    + +
  5. + +The example disk image is a modified version of the one made by Kevin +Lawton for the plex86 Project (www.plex86.org). + +
+ + + +

3.9 Linux Kernel Compilation

+ +

+You can use any linux kernel with QEMU. However, if you want to use +qemu-fast to get maximum performances, you must use a modified +guest kernel. If you are using a 2.6 guest kernel, you can use +directly the patch `linux-2.6-qemu-fast.patch' made by Rusty +Russel available in the QEMU source archive. Otherwise, you can make the +following changes by hand to the Linux kernel: + + + +

    +
  1. + +The kernel must be mapped at 0x90000000 (the default is +0xc0000000). You must modify only two lines in the kernel source: + +In `include/asm/page.h', replace + +
    +#define __PAGE_OFFSET           (0xc0000000)
    +
    + +by + +
    +#define __PAGE_OFFSET           (0x90000000)
    +
    + +And in `arch/i386/vmlinux.lds', replace + +
    +  . = 0xc0000000 + 0x100000;
    +
    + +by + +
    +  . = 0x90000000 + 0x100000;
    +
    + +
  2. + +If you want to enable SMP (Symmetric Multi-Processing) support, you +must make the following change in `include/asm/fixmap.h'. Replace + +
    +#define FIXADDR_TOP	(0xffffX000UL)
    +
    + +by + +
    +#define FIXADDR_TOP	(0xa7ffX000UL)
    +
    + +(X is 'e' or 'f' depending on the kernel version). Although you can +use an SMP kernel with QEMU, it only supports one CPU. + +
  3. + +If you are not using a 2.6 kernel as host kernel but if you use a target +2.6 kernel, you must also ensure that the 'HZ' define is set to 100 +(1000 is the default) as QEMU cannot currently emulate timers at +frequencies greater than 100 Hz on host Linux systems < 2.6. In +`include/asm/param.h', replace: + + +
    +# define HZ		1000		/* Internal kernel timer frequency */
    +
    + +by + +
    +# define HZ		100		/* Internal kernel timer frequency */
    +
    + +
+ +

+The file config-2.x.x gives the configuration of the example kernels. + + +

+Just type + +

+make bzImage
+
+ +

+As you would do to make a real kernel. Then you can use with QEMU +exactly the same kernel as you would boot on your PC (in +`arch/i386/boot/bzImage'). + + + + +

3.10 GDB usage

+ +

+QEMU has a primitive support to work with gdb, so that you can do +'Ctrl-C' while the virtual machine is running and inspect its state. + + +

+In order to use gdb, launch qemu with the '-s' option. It will wait for a +gdb connection: + +

+> qemu -s -kernel arch/i386/boot/bzImage -hda root-2.4.20.img -append "root=/dev/hda"
+Connected to host network interface: tun0
+Waiting gdb connection on port 1234
+
+ +

+Then launch gdb on the 'vmlinux' executable: + +

+> gdb vmlinux
+
+ +

+In gdb, connect to QEMU: + +

+(gdb) target remote localhost:1234
+
+ +

+Then you can use gdb normally. For example, type 'c' to launch the kernel: + +

+(gdb) c
+
+ +

+Here are some useful tips in order to use gdb on system code: + + + +

    +
  1. + +Use info reg to display all the CPU registers. +
  2. + +Use x/10i $eip to display the code at the PC position. +
  3. + +Use set architecture i8086 to dump 16 bit code. Then use +x/10i $cs*16+*eip to dump the code at the PC position. +
+ + + +

3.11 Target OS specific information

+ + + +

3.11.1 Linux

+ +

+To have access to SVGA graphic modes under X11, use the vesa or +the cirrus X11 driver. For optimal performances, use 16 bit +color depth in the guest and the host OS. + + +

+When using a 2.6 guest Linux kernel, you should add the option +clock=pit on the kernel command line because the 2.6 Linux +kernels make very strict real time clock checks by default that QEMU +cannot simulate exactly. + + + + +

3.11.2 Windows

+ +

+If you have a slow host, using Windows 95 is better as it gives the +best speed. Windows 2000 is also a good choice. + + + + +

3.11.2.1 SVGA graphic modes support

+ +

+QEMU emulates a Cirrus Logic GD5446 Video +card. All Windows versions starting from Windows 95 should recognize +and use this graphic card. For optimal performances, use 16 bit color +depth in the guest and the host OS. + + + + +

3.11.2.2 CPU usage reduction

+ +

+Windows 9x does not correctly use the CPU HLT +instruction. The result is that it takes host CPU cycles even when +idle. You can install the utility from +http://www.user.cityline.ru/~maxamn/amnhltm.zip to solve this +problem. Note that no such tool is needed for NT, 2000 or XP. + + + + +

3.11.2.3 Windows 2000 disk full problems

+ +

+Currently (release 0.6.0) QEMU has a bug which gives a disk +full error during installation of some releases of Windows 2000. The +workaround is to stop QEMU as soon as you notice that your disk image +size is growing too fast (monitor it with ls -ls). Then +relaunch QEMU to continue the installation. If you still experience +the problem, relaunch QEMU again. + + +

+Future QEMU releases are likely to correct this bug. + + + + +

3.11.2.4 Windows XP security problems

+ +

+Some releases of Windows XP install correctly but give a security +error when booting: + +

+A problem is preventing Windows from accurately checking the
+license for this computer. Error code: 0x800703e6.
+
+ +

+The only known workaround is to boot in Safe mode +without networking support. + + +

+Future QEMU releases are likely to correct this bug. + + + + +

3.11.3 MS-DOS and FreeDOS

+ + + +

3.11.3.1 CPU usage reduction

+ +

+DOS does not correctly use the CPU HLT instruction. The result is that +it takes host CPU cycles even when idle. You can install the utility +from http://www.vmware.com/software/dosidle210.zip to solve this +problem. + + + + +

4. QEMU PowerPC System emulator invocation

+ +

+Use the executable `qemu-system-ppc' to simulate a complete PREP +or PowerMac PowerPC system. + + +

+QEMU emulates the following PowerMac peripherials: + + + +

    +
  • + +UniNorth PCI Bridge +
  • + +PCI VGA compatible card with VESA Bochs Extensions +
  • + +2 PMAC IDE interfaces with hard disk and CD-ROM support +
  • + +NE2000 PCI adapters +
  • + +Non Volatile RAM +
  • + +VIA-CUDA with ADB keyboard and mouse. +
+ +

+QEMU emulates the following PREP peripherials: + + + +

    +
  • + +PCI Bridge +
  • + +PCI VGA compatible card with VESA Bochs Extensions +
  • + +2 IDE interfaces with hard disk and CD-ROM support +
  • + +Floppy disk +
  • + +NE2000 network adapters +
  • + +Serial port +
  • + +PREP Non Volatile RAM +
  • + +PC compatible keyboard and mouse. +
+ +

+QEMU uses the Open Hack'Ware Open Firmware Compatible BIOS available at +http://site.voila.fr/jmayer/OpenHackWare/index.htm. + + +

+You can read the qemu PC system emulation chapter to have more +informations about QEMU usage. + + +

+The following options are specific to the PowerPC emulation: + + +

+ +
@option{-prep} +
+Simulate a PREP system (default is PowerMAC) + +
@option{-g WxH[xDEPTH]} +
+Set the initial VGA graphic mode. The default is 800x600x15. + +
+ +

+More information is available at +http://jocelyn.mayer.free.fr/qemu-ppc/. + + + + +

5. QEMU User space emulator invocation

+ + + +

5.1 Quick Start

+ +

+In order to launch a Linux process, QEMU needs the process executable +itself and all the target (x86) dynamic libraries used by it. + + + +

    + +
  • On x86, you can just try to launch any process by using the native + +libraries: + + +
    +qemu-i386 -L / /bin/ls
    +
    + +-L / tells that the x86 dynamic linker must be searched with a +`/' prefix. + +
  • Since QEMU is also a linux process, you can launch qemu with qemu (NOTE: you can only do that if you compiled QEMU from the sources): + + +
    +qemu-i386 -L / qemu-i386 -L / /bin/ls
    +
    + +
  • On non x86 CPUs, you need first to download at least an x86 glibc + +(`qemu-runtime-i386-XXX-.tar.gz' on the QEMU web page). Ensure that +LD_LIBRARY_PATH is not set: + + +
    +unset LD_LIBRARY_PATH 
    +
    + +Then you can launch the precompiled `ls' x86 executable: + + +
    +qemu-i386 tests/i386/ls
    +
    + +You can look at `qemu-binfmt-conf.sh' so that +QEMU is automatically launched by the Linux kernel when you try to +launch x86 executables. It requires the binfmt_misc module in the +Linux kernel. + +
  • The x86 version of QEMU is also included. You can try weird things such as: + + +
    +qemu-i386 /usr/local/qemu-i386/bin/qemu-i386 /usr/local/qemu-i386/bin/ls-i386
    +
    + +
+ + + +

5.2 Wine launch

+ + +
    + +
  • Ensure that you have a working QEMU with the x86 glibc + +distribution (see previous section). In order to verify it, you must be +able to do: + + +
    +qemu-i386 /usr/local/qemu-i386/bin/ls-i386
    +
    + +
  • Download the binary x86 Wine install + +(`qemu-XXX-i386-wine.tar.gz' on the QEMU web page). + +
  • Configure Wine on your account. Look at the provided script + +`/usr/local/qemu-i386/bin/wine-conf.sh'. Your previous +${HOME}/.wine directory is saved to ${HOME}/.wine.org. + +
  • Then you can try the example `putty.exe': + + +
    +qemu-i386 /usr/local/qemu-i386/wine/bin/wine /usr/local/qemu-i386/wine/c/Program\ Files/putty.exe
    +
    + +
+ + + +

5.3 Command line options

+ + +
+usage: qemu-i386 [-h] [-d] [-L path] [-s size] program [arguments...]
+
+ +
+ +
@option{-h} +
+Print the help +
@option{-L path} +
+Set the x86 elf interpreter prefix (default=/usr/local/qemu-i386) +
@option{-s size} +
+Set the x86 stack size in bytes (default=524288) +
+ +

+Debug options: + + +

+ +
@option{-d} +
+Activate log (logfile=/tmp/qemu.log) +
@option{-p pagesize} +
+Act as if the host page size was 'pagesize' bytes +
+ + + +

6. Compilation from the sources

+ + + +

6.1 Linux/BSD

+ +

+Read the `README' which gives the related information. + + + + +

6.2 Windows

+ + +
    +
  • Install the current versions of MSYS and MinGW from + +http://www.mingw.org/. You can find detailed installation +instructions in the download section and the FAQ. + +
  • Download + +the MinGW development library of SDL 1.2.x +(`SDL-devel-1.2.x-mingw32.tar.gz') from +http://www.libsdl.org. Unpack it in a temporary place, and +unpack the archive `i386-mingw32msvc.tar.gz' in the MinGW tool +directory. Edit the `sdl-config' script so that it gives the +correct SDL directory when invoked. + +
  • Extract the current version of QEMU. + + +
  • Start the MSYS shell (file `msys.bat'). + +
  • Change to the QEMU directory. Launch `./configure' and + +`make'. If you have problems using SDL, verify that +`sdl-config' can be launched from the MSYS command line. + +
  • You can install QEMU in `Program Files/Qemu' by typing + +`make install'. Don't forget to copy `SDL.dll' in +`Program Files/Qemu'. + +
+ + + +

6.3 Cross compilation for Windows with Linux

+ + +
    +
  • + +Install the MinGW cross compilation tools available at +http://www.mingw.org/. + +
  • + +Install the Win32 version of SDL (http://www.libsdl.org) by +unpacking `i386-mingw32msvc.tar.gz'. Set up the PATH environment +variable so that `i386-mingw32msvc-sdl-config' can be launched by +the QEMU configuration script. + +
  • + +Configure QEMU for Windows cross compilation: + +
    +./configure --enable-mingw32
    +
    + +If necessary, you can change the cross-prefix according to the prefix +choosen for the MinGW tools with --cross-prefix. You can also use +--prefix to set the Win32 install path. + +
  • You can install QEMU in the installation directory by typing + +`make install'. Don't forget to copy `SDL.dll' in the +installation directory. + +
+ +

+Note: Currently, Wine does not seem able to launch +QEMU for Win32. + + + + +

6.4 Mac OS X

+ +

+The Mac OS X patches are not fully merged in QEMU, so you should look +at the QEMU mailing list archive to have all the necessary +information. + + +


+This document was generated on 19 May 2005 using +texi2html 1.56k. + + diff --git a/tools/ioemu/qemu-doc.texi b/tools/ioemu/qemu-doc.texi new file mode 100644 index 0000000000..c262ee7e9c --- /dev/null +++ b/tools/ioemu/qemu-doc.texi @@ -0,0 +1,1296 @@ +\input texinfo @c -*- texinfo -*- + +@iftex +@settitle QEMU CPU Emulator User Documentation +@titlepage +@sp 7 +@center @titlefont{QEMU CPU Emulator User Documentation} +@sp 3 +@end titlepage +@end iftex + +@chapter Introduction + +@section Features + +QEMU is a FAST! processor emulator using dynamic translation to +achieve good emulation speed. + +QEMU has two operating modes: + +@itemize @minus + +@item +Full system emulation. In this mode, QEMU emulates a full system (for +example a PC), including a processor and various peripherials. It can +be used to launch different Operating Systems without rebooting the +PC or to debug system code. + +@item +User mode emulation (Linux host only). In this mode, QEMU can launch +Linux processes compiled for one CPU on another CPU. It can be used to +launch the Wine Windows API emulator (@url{http://www.winehq.org}) or +to ease cross-compilation and cross-debugging. + +@end itemize + +As QEMU requires no host kernel driver to run, it is very safe and +easy to use. + +For system emulation, the following hardware targets are supported: +@itemize +@item PC (x86 processor) +@item PREP (PowerPC processor) +@item PowerMac (PowerPC processor, in progress) +@end itemize + +For user emulation, x86, PowerPC, ARM, and SPARC CPUs are supported. + +@chapter Installation + +If you want to compile QEMU yourself, see @ref{compilation}. + +@section Linux + +Download the binary distribution (@file{qemu-XXX-i386.tar.gz}) and +untar it as root in @file{/}: + +@example +su +cd / +tar zxvf /tmp/qemu-XXX-i386.tar.gz +@end example + +@section Windows + +Download the experimental binary installer at +@url{http://www.freeoszoo.org/download.php}. + +@section Mac OS X + +Download the experimental binary installer at +@url{http://www.freeoszoo.org/download.php}. + +@chapter QEMU PC System emulator invocation + +@section Introduction + +@c man begin DESCRIPTION + +The QEMU System emulator simulates a complete PC. + +In order to meet specific user needs, two versions of QEMU are +available: + +@enumerate + +@item +@code{qemu-fast} uses the host Memory Management Unit (MMU) to +simulate the x86 MMU. It is @emph{fast} but has limitations because +the whole 4 GB address space cannot be used and some memory mapped +peripherials cannot be emulated accurately yet. Therefore, a specific +guest Linux kernel can be used (@xref{linux_compile}) as guest +OS. + +Moreover there is no separation between the host and target address +spaces, so it offers no security (the target OS can modify the +@code{qemu-fast} code by writing at the right addresses). + +@item +@code{qemu} uses a software MMU. It is about @emph{two times slower} +but gives a more accurate emulation and a complete separation between +the host and target address spaces. + +@end enumerate + +QEMU emulates the following PC peripherials: + +@itemize @minus +@item +i440FX host PCI bridge and PIIX3 PCI to ISA bridge +@item +Cirrus CLGD 5446 PCI VGA card or dummy VGA card with Bochs VESA +extensions (hardware level, including all non standard modes). +@item +PS/2 mouse and keyboard +@item +2 PCI IDE interfaces with hard disk and CD-ROM support +@item +Floppy disk +@item +NE2000 PCI network adapters +@item +Serial ports +@item +Soundblaster 16 card +@end itemize + +QEMU uses the PC BIOS from the Bochs project and the Plex86/Bochs LGPL +VGA BIOS. + +@c man end + +@section Quick Start + +Download and uncompress the linux image (@file{linux.img}) and type: + +@example +qemu linux.img +@end example + +Linux should boot and give you a prompt. + +@section Invocation + +@example +@c man begin SYNOPSIS +usage: qemu [options] [disk_image] +@c man end +@end example + +@c man begin OPTIONS +@var{disk_image} is a raw hard disk image for IDE hard disk 0. + +General options: +@table @option +@item -fda file +@item -fdb file +Use @var{file} as floppy disk 0/1 image (@xref{disk_images}). You can +use the host floppy by using @file{/dev/fd0} as filename. + +@item -hda file +@item -hdb file +@item -hdc file +@item -hdd file +Use @var{file} as hard disk 0, 1, 2 or 3 image (@xref{disk_images}). + +@item -cdrom file +Use @var{file} as CD-ROM image (you cannot use @option{-hdc} and and +@option{-cdrom} at the same time). You can use the host CD-ROM by +using @file{/dev/cdrom} as filename. + +@item -boot [a|c|d] +Boot on floppy (a), hard disk (c) or CD-ROM (d). Hard disk boot is +the default. + +@item -snapshot +Write to temporary files instead of disk image files. In this case, +the raw disk image you use is not written back. You can however force +the write back by pressing @key{C-a s} (@xref{disk_images}). + +@item -m megs +Set virtual RAM size to @var{megs} megabytes. Default is 128 MB. + +@item -nographic + +Normally, QEMU uses SDL to display the VGA output. With this option, +you can totally disable graphical output so that QEMU is a simple +command line application. The emulated serial port is redirected on +the console. Therefore, you can still use QEMU to debug a Linux kernel +with a serial console. + +@item -enable-audio + +The SB16 emulation is disabled by default as it may give problems with +Windows. You can enable it manually with this option. + +@item -localtime +Set the real time clock to local time (the default is to UTC +time). This option is needed to have correct date in MS-DOS or +Windows. + +@item -full-screen +Start in full screen. + +@end table + +Network options: + +@table @option + +@item -n script +Set TUN/TAP network init script [default=/etc/qemu-ifup]. This script +is launched to configure the host network interface (usually tun0) +corresponding to the virtual NE2000 card. + +@item -macaddr addr + +Set the mac address of the first interface (the format is +aa:bb:cc:dd:ee:ff in hexa). The mac address is incremented for each +new network interface. + +@item -tun-fd fd +Assumes @var{fd} talks to a tap/tun host network interface and use +it. Read @url{http://bellard.org/qemu/tetrinet.html} to have an +example of its use. + +@item -user-net +Use the user mode network stack. This is the default if no tun/tap +network init script is found. + +@item -tftp prefix +When using the user mode network stack, activate a built-in TFTP +server. All filenames beginning with @var{prefix} can be downloaded +from the host to the guest using a TFTP client. The TFTP client on the +guest must be configured in binary mode (use the command @code{bin} of +the Unix TFTP client). The host IP address on the guest is as usual +10.0.2.2. + +@item -smb dir +When using the user mode network stack, activate a built-in SMB +server so that Windows OSes can access to the host files in @file{dir} +transparently. + +In the guest Windows OS, the line: +@example +10.0.2.4 smbserver +@end example +must be added in the file @file{C:\WINDOWS\LMHOSTS} (for windows 9x/Me) +or @file{C:\WINNT\SYSTEM32\DRIVERS\ETC\LMHOSTS} (Windows NT/2000). + +Then @file{dir} can be accessed in @file{\\smbserver\qemu}. + +Note that a SAMBA server must be installed on the host OS in +@file{/usr/sbin/smbd}. QEMU was tested succesfully with smbd version +2.2.7a from the Red Hat 9. + +@item -redir [tcp|udp]:host-port:[guest-host]:guest-port + +When using the user mode network stack, redirect incoming TCP or UDP +connections to the host port @var{host-port} to the guest +@var{guest-host} on guest port @var{guest-port}. If @var{guest-host} +is not specified, its value is 10.0.2.15 (default address given by the +built-in DHCP server). + +For example, to redirect host X11 connection from screen 1 to guest +screen 0, use the following: + +@example +# on the host +qemu -redir tcp:6001::6000 [...] +# this host xterm should open in the guest X11 server +xterm -display :1 +@end example + +To redirect telnet connections from host port 5555 to telnet port on +the guest, use the following: + +@example +# on the host +qemu -redir tcp:5555::23 [...] +telnet localhost 5555 +@end example + +Then when you use on the host @code{telnet localhost 5555}, you +connect to the guest telnet server. + +@item -dummy-net +Use the dummy network stack: no packet will be received by the network +cards. + +@end table + +Linux boot specific. When using this options, you can use a given +Linux kernel without installing it in the disk image. It can be useful +for easier testing of various kernels. + +@table @option + +@item -kernel bzImage +Use @var{bzImage} as kernel image. + +@item -append cmdline +Use @var{cmdline} as kernel command line + +@item -initrd file +Use @var{file} as initial ram disk. + +@end table + +Debug/Expert options: +@table @option + +@item -serial dev +Redirect the virtual serial port to host device @var{dev}. Available +devices are: +@table @code +@item vc +Virtual console +@item pty +[Linux only] Pseudo TTY (a new PTY is automatically allocated) +@item null +void device +@item stdio +[Unix only] standard input/output +@end table +The default device is @code{vc} in graphical mode and @code{stdio} in +non graphical mode. + +This option can be used several times to simulate up to 4 serials +ports. + +@item -monitor dev +Redirect the monitor to host device @var{dev} (same devices as the +serial port). +The default device is @code{vc} in graphical mode and @code{stdio} in +non graphical mode. + +@item -s +Wait gdb connection to port 1234 (@xref{gdb_usage}). +@item -p port +Change gdb connection port. +@item -S +Do not start CPU at startup (you must type 'c' in the monitor). +@item -d +Output log in /tmp/qemu.log +@item -isa +Simulate an ISA-only system (default is PCI system). +@item -std-vga +Simulate a standard VGA card with Bochs VBE extensions (default is +Cirrus Logic GD5446 PCI VGA) +@item -loadvm file +Start right away with a saved state (@code{loadvm} in monitor) +@end table + +@c man end + +@section Keys + +@c man begin OPTIONS + +During the graphical emulation, you can use the following keys: +@table @key +@item Ctrl-Alt-f +Toggle full screen + +@item Ctrl-Alt-n +Switch to virtual console 'n'. Standard console mappings are: +@table @emph +@item 1 +Target system display +@item 2 +Monitor +@item 3 +Serial port +@end table + +@item Ctrl-Alt +Toggle mouse and keyboard grab. +@end table + +In the virtual consoles, you can use @key{Ctrl-Up}, @key{Ctrl-Down}, +@key{Ctrl-PageUp} and @key{Ctrl-PageDown} to move in the back log. + +During emulation, if you are using the @option{-nographic} option, use +@key{Ctrl-a h} to get terminal commands: + +@table @key +@item Ctrl-a h +Print this help +@item Ctrl-a x +Exit emulatior +@item Ctrl-a s +Save disk data back to file (if -snapshot) +@item Ctrl-a b +Send break (magic sysrq in Linux) +@item Ctrl-a c +Switch between console and monitor +@item Ctrl-a Ctrl-a +Send Ctrl-a +@end table +@c man end + +@ignore + +@setfilename qemu +@settitle QEMU System Emulator + +@c man begin SEEALSO +The HTML documentation of QEMU for more precise information and Linux +user mode emulator invocation. +@c man end + +@c man begin AUTHOR +Fabrice Bellard +@c man end + +@end ignore + +@end ignore + + +@section QEMU Monitor + +The QEMU monitor is used to give complex commands to the QEMU +emulator. You can use it to: + +@itemize @minus + +@item +Remove or insert removable medias images +(such as CD-ROM or floppies) + +@item +Freeze/unfreeze the Virtual Machine (VM) and save or restore its state +from a disk file. + +@item Inspect the VM state without an external debugger. + +@end itemize + +@subsection Commands + +The following commands are available: + +@table @option + +@item help or ? [cmd] +Show the help for all commands or just for command @var{cmd}. + +@item commit +Commit changes to the disk images (if -snapshot is used) + +@item info subcommand +show various information about the system state + +@table @option +@item info network +show the network state +@item info block +show the block devices +@item info registers +show the cpu registers +@item info history +show the command line history +@end table + +@item q or quit +Quit the emulator. + +@item eject [-f] device +Eject a removable media (use -f to force it). + +@item change device filename +Change a removable media. + +@item screendump filename +Save screen into PPM image @var{filename}. + +@item log item1[,...] +Activate logging of the specified items to @file{/tmp/qemu.log}. + +@item savevm filename +Save the whole virtual machine state to @var{filename}. + +@item loadvm filename +Restore the whole virtual machine state from @var{filename}. + +@item stop +Stop emulation. + +@item c or cont +Resume emulation. + +@item gdbserver [port] +Start gdbserver session (default port=1234) + +@item x/fmt addr +Virtual memory dump starting at @var{addr}. + +@item xp /fmt addr +Physical memory dump starting at @var{addr}. + +@var{fmt} is a format which tells the command how to format the +data. Its syntax is: @option{/@{count@}@{format@}@{size@}} + +@table @var +@item count +is the number of items to be dumped. + +@item format +can be x (hexa), d (signed decimal), u (unsigned decimal), o (octal), +c (char) or i (asm instruction). + +@item size +can be b (8 bits), h (16 bits), w (32 bits) or g (64 bits). On x86, +@code{h} or @code{w} can be specified with the @code{i} format to +respectively select 16 or 32 bit code instruction size. + +@end table + +Examples: +@itemize +@item +Dump 10 instructions at the current instruction pointer: +@example +(qemu) x/10i $eip +0x90107063: ret +0x90107064: sti +0x90107065: lea 0x0(%esi,1),%esi +0x90107069: lea 0x0(%edi,1),%edi +0x90107070: ret +0x90107071: jmp 0x90107080 +0x90107073: nop +0x90107074: nop +0x90107075: nop +0x90107076: nop +@end example + +@item +Dump 80 16 bit values at the start of the video memory. +@example +(qemu) xp/80hx 0xb8000 +0x000b8000: 0x0b50 0x0b6c 0x0b65 0x0b78 0x0b38 0x0b36 0x0b2f 0x0b42 +0x000b8010: 0x0b6f 0x0b63 0x0b68 0x0b73 0x0b20 0x0b56 0x0b47 0x0b41 +0x000b8020: 0x0b42 0x0b69 0x0b6f 0x0b73 0x0b20 0x0b63 0x0b75 0x0b72 +0x000b8030: 0x0b72 0x0b65 0x0b6e 0x0b74 0x0b2d 0x0b63 0x0b76 0x0b73 +0x000b8040: 0x0b20 0x0b30 0x0b35 0x0b20 0x0b4e 0x0b6f 0x0b76 0x0b20 +0x000b8050: 0x0b32 0x0b30 0x0b30 0x0b33 0x0720 0x0720 0x0720 0x0720 +0x000b8060: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 +0x000b8070: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 +0x000b8080: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 +0x000b8090: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 +@end example +@end itemize + +@item p or print/fmt expr + +Print expression value. Only the @var{format} part of @var{fmt} is +used. + +@item sendkey keys + +Send @var{keys} to the emulator. Use @code{-} to press several keys +simultaneously. Example: +@example +sendkey ctrl-alt-f1 +@end example + +This command is useful to send keys that your graphical user interface +intercepts at low level, such as @code{ctrl-alt-f1} in X Window. + +@item system_reset + +Reset the system. + +@end table + +@subsection Integer expressions + +The monitor understands integers expressions for every integer +argument. You can use register names to get the value of specifics +CPU registers by prefixing them with @emph{$}. + +@node disk_images +@section Disk Images + +@subsection Raw disk images + +The disk images can simply be raw images of the hard disk. You can +create them with the command: +@example +dd of=myimage bs=1024 seek=mysize count=0 +@end example +where @var{myimage} is the image filename and @var{mysize} is its size +in kilobytes. + +@subsection Snapshot mode + +If you use the option @option{-snapshot}, all disk images are +considered as read only. When sectors in written, they are written in +a temporary file created in @file{/tmp}. You can however force the +write back to the raw disk images by pressing @key{C-a s}. + +NOTE: The snapshot mode only works with raw disk images. + +@subsection Copy On Write disk images + +QEMU also supports user mode Linux +(@url{http://user-mode-linux.sourceforge.net/}) Copy On Write (COW) +disk images. The COW disk images are much smaller than normal images +as they store only modified sectors. They also permit the use of the +same disk image template for many users. + +To create a COW disk images, use the command: + +@example +qemu-mkcow -f myrawimage.bin mycowimage.cow +@end example + +@file{myrawimage.bin} is a raw image you want to use as original disk +image. It will never be written to. + +@file{mycowimage.cow} is the COW disk image which is created by +@code{qemu-mkcow}. You can use it directly with the @option{-hdx} +options. You must not modify the original raw disk image if you use +COW images, as COW images only store the modified sectors from the raw +disk image. QEMU stores the original raw disk image name and its +modified time in the COW disk image so that chances of mistakes are +reduced. + +If the raw disk image is not read-only, by pressing @key{C-a s} you +can flush the COW disk image back into the raw disk image, as in +snapshot mode. + +COW disk images can also be created without a corresponding raw disk +image. It is useful to have a big initial virtual disk image without +using much disk space. Use: + +@example +qemu-mkcow mycowimage.cow 1024 +@end example + +to create a 1 gigabyte empty COW disk image. + +NOTES: +@enumerate +@item +COW disk images must be created on file systems supporting +@emph{holes} such as ext2 or ext3. +@item +Since holes are used, the displayed size of the COW disk image is not +the real one. To know it, use the @code{ls -ls} command. +@end enumerate + +@subsection Convert VMware disk images to raw disk images + +You can use the tool @file{vmdk2raw} to convert VMware disk images to +raw disk images directly usable by QEMU. The syntax is: +@example +vmdk2raw vmware_image output_image +@end example + +@section Network emulation + +QEMU simulates up to 6 networks cards (NE2000 boards). Each card can +be connected to a specific host network interface. + +@subsection Using tun/tap network interface + +This is the standard way to emulate network. QEMU adds a virtual +network device on your host (called @code{tun0}), and you can then +configure it as if it was a real ethernet card. + +As an example, you can download the @file{linux-test-xxx.tar.gz} +archive and copy the script @file{qemu-ifup} in @file{/etc} and +configure properly @code{sudo} so that the command @code{ifconfig} +contained in @file{qemu-ifup} can be executed as root. You must verify +that your host kernel supports the TUN/TAP network interfaces: the +device @file{/dev/net/tun} must be present. + +See @ref{direct_linux_boot} to have an example of network use with a +Linux distribution. + +@subsection Using the user mode network stack + +By using the option @option{-user-net} or if you have no tun/tap init +script, QEMU uses a completely user mode network stack (you don't need +root priviledge to use the virtual network). The virtual network +configuration is the following: + +@example + +QEMU Virtual Machine <------> Firewall/DHCP server <-----> Internet + (10.0.2.x) | (10.0.2.2) + | + ----> DNS server (10.0.2.3) + | + ----> SMB server (10.0.2.4) +@end example + +The QEMU VM behaves as if it was behind a firewall which blocks all +incoming connections. You can use a DHCP client to automatically +configure the network in the QEMU VM. + +In order to check that the user mode network is working, you can ping +the address 10.0.2.2 and verify that you got an address in the range +10.0.2.x from the QEMU virtual DHCP server. + +Note that @code{ping} is not supported reliably to the internet as it +would require root priviledges. It means you can only ping the local +router (10.0.2.2). + +When using the built-in TFTP server, the router is also the TFTP +server. + +When using the @option{-redir} option, TCP or UDP connections can be +redirected from the host to the guest. It allows for example to +redirect X11, telnet or SSH connections. + +@node direct_linux_boot +@section Direct Linux Boot + +This section explains how to launch a Linux kernel inside QEMU without +having to make a full bootable image. It is very useful for fast Linux +kernel testing. The QEMU network configuration is also explained. + +@enumerate +@item +Download the archive @file{linux-test-xxx.tar.gz} containing a Linux +kernel and a disk image. + +@item Optional: If you want network support (for example to launch X11 examples), you +must copy the script @file{qemu-ifup} in @file{/etc} and configure +properly @code{sudo} so that the command @code{ifconfig} contained in +@file{qemu-ifup} can be executed as root. You must verify that your host +kernel supports the TUN/TAP network interfaces: the device +@file{/dev/net/tun} must be present. + +When network is enabled, there is a virtual network connection between +the host kernel and the emulated kernel. The emulated kernel is seen +from the host kernel at IP address 172.20.0.2 and the host kernel is +seen from the emulated kernel at IP address 172.20.0.1. + +@item Launch @code{qemu.sh}. You should have the following output: + +@example +> ./qemu.sh +Connected to host network interface: tun0 +Linux version 2.4.21 (bellard@voyager.localdomain) (gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) #5 Tue Nov 11 18:18:53 CET 2003 +BIOS-provided physical RAM map: + BIOS-e801: 0000000000000000 - 000000000009f000 (usable) + BIOS-e801: 0000000000100000 - 0000000002000000 (usable) +32MB LOWMEM available. +On node 0 totalpages: 8192 +zone(0): 4096 pages. +zone(1): 4096 pages. +zone(2): 0 pages. +Kernel command line: root=/dev/hda sb=0x220,5,1,5 ide2=noprobe ide3=noprobe ide4=noprobe ide5=noprobe console=ttyS0 +ide_setup: ide2=noprobe +ide_setup: ide3=noprobe +ide_setup: ide4=noprobe +ide_setup: ide5=noprobe +Initializing CPU#0 +Detected 2399.621 MHz processor. +Console: colour EGA 80x25 +Calibrating delay loop... 4744.80 BogoMIPS +Memory: 28872k/32768k available (1210k kernel code, 3508k reserved, 266k data, 64k init, 0k highmem) +Dentry cache hash table entries: 4096 (order: 3, 32768 bytes) +Inode cache hash table entries: 2048 (order: 2, 16384 bytes) +Mount cache hash table entries: 512 (order: 0, 4096 bytes) +Buffer-cache hash table entries: 1024 (order: 0, 4096 bytes) +Page-cache hash table entries: 8192 (order: 3, 32768 bytes) +CPU: Intel Pentium Pro stepping 03 +Checking 'hlt' instruction... OK. +POSIX conformance testing by UNIFIX +Linux NET4.0 for Linux 2.4 +Based upon Swansea University Computer Society NET3.039 +Initializing RT netlink socket +apm: BIOS not found. +Starting kswapd +Journalled Block Device driver loaded +Detected PS/2 Mouse Port. +pty: 256 Unix98 ptys configured +Serial driver version 5.05c (2001-07-08) with no serial options enabled +ttyS00 at 0x03f8 (irq = 4) is a 16450 +ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com) +Last modified Nov 1, 2000 by Paul Gortmaker +NE*000 ethercard probe at 0x300: 52 54 00 12 34 56 +eth0: NE2000 found at 0x300, using IRQ 9. +RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize +Uniform Multi-Platform E-IDE driver Revision: 7.00beta4-2.4 +ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xx +hda: QEMU HARDDISK, ATA DISK drive +ide0 at 0x1f0-0x1f7,0x3f6 on irq 14 +hda: attached ide-disk driver. +hda: 20480 sectors (10 MB) w/256KiB Cache, CHS=20/16/63 +Partition check: + hda: +Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996 +NET4: Linux TCP/IP 1.0 for NET4.0 +IP Protocols: ICMP, UDP, TCP, IGMP +IP: routing cache hash table of 512 buckets, 4Kbytes +TCP: Hash tables configured (established 2048 bind 4096) +NET4: Unix domain sockets 1.0/SMP for Linux NET4.0. +EXT2-fs warning: mounting unchecked fs, running e2fsck is recommended +VFS: Mounted root (ext2 filesystem). +Freeing unused kernel memory: 64k freed + +Linux version 2.4.21 (bellard@voyager.localdomain) (gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) #5 Tue Nov 11 18:18:53 CET 2003 + +QEMU Linux test distribution (based on Redhat 9) + +Type 'exit' to halt the system + +sh-2.05b# +@end example + +@item +Then you can play with the kernel inside the virtual serial console. You +can launch @code{ls} for example. Type @key{Ctrl-a h} to have an help +about the keys you can type inside the virtual serial console. In +particular, use @key{Ctrl-a x} to exit QEMU and use @key{Ctrl-a b} as +the Magic SysRq key. + +@item +If the network is enabled, launch the script @file{/etc/linuxrc} in the +emulator (don't forget the leading dot): +@example +. /etc/linuxrc +@end example + +Then enable X11 connections on your PC from the emulated Linux: +@example +xhost +172.20.0.2 +@end example + +You can now launch @file{xterm} or @file{xlogo} and verify that you have +a real Virtual Linux system ! + +@end enumerate + +NOTES: +@enumerate +@item +A 2.5.74 kernel is also included in the archive. Just +replace the bzImage in qemu.sh to try it. + +@item +qemu-fast creates a temporary file in @var{$QEMU_TMPDIR} (@file{/tmp} is the +default) containing all the simulated PC memory. If possible, try to use +a temporary directory using the tmpfs filesystem to avoid too many +unnecessary disk accesses. + +@item +In order to exit cleanly from qemu, you can do a @emph{shutdown} inside +qemu. qemu will automatically exit when the Linux shutdown is done. + +@item +You can boot slightly faster by disabling the probe of non present IDE +interfaces. To do so, add the following options on the kernel command +line: +@example +ide1=noprobe ide2=noprobe ide3=noprobe ide4=noprobe ide5=noprobe +@end example + +@item +The example disk image is a modified version of the one made by Kevin +Lawton for the plex86 Project (@url{www.plex86.org}). + +@end enumerate + +@node linux_compile +@section Linux Kernel Compilation + +You can use any linux kernel with QEMU. However, if you want to use +@code{qemu-fast} to get maximum performances, you must use a modified +guest kernel. If you are using a 2.6 guest kernel, you can use +directly the patch @file{linux-2.6-qemu-fast.patch} made by Rusty +Russel available in the QEMU source archive. Otherwise, you can make the +following changes @emph{by hand} to the Linux kernel: + +@enumerate +@item +The kernel must be mapped at 0x90000000 (the default is +0xc0000000). You must modify only two lines in the kernel source: + +In @file{include/asm/page.h}, replace +@example +#define __PAGE_OFFSET (0xc0000000) +@end example +by +@example +#define __PAGE_OFFSET (0x90000000) +@end example + +And in @file{arch/i386/vmlinux.lds}, replace +@example + . = 0xc0000000 + 0x100000; +@end example +by +@example + . = 0x90000000 + 0x100000; +@end example + +@item +If you want to enable SMP (Symmetric Multi-Processing) support, you +must make the following change in @file{include/asm/fixmap.h}. Replace +@example +#define FIXADDR_TOP (0xffffX000UL) +@end example +by +@example +#define FIXADDR_TOP (0xa7ffX000UL) +@end example +(X is 'e' or 'f' depending on the kernel version). Although you can +use an SMP kernel with QEMU, it only supports one CPU. + +@item +If you are not using a 2.6 kernel as host kernel but if you use a target +2.6 kernel, you must also ensure that the 'HZ' define is set to 100 +(1000 is the default) as QEMU cannot currently emulate timers at +frequencies greater than 100 Hz on host Linux systems < 2.6. In +@file{include/asm/param.h}, replace: + +@example +# define HZ 1000 /* Internal kernel timer frequency */ +@end example +by +@example +# define HZ 100 /* Internal kernel timer frequency */ +@end example + +@end enumerate + +The file config-2.x.x gives the configuration of the example kernels. + +Just type +@example +make bzImage +@end example + +As you would do to make a real kernel. Then you can use with QEMU +exactly the same kernel as you would boot on your PC (in +@file{arch/i386/boot/bzImage}). + +@node gdb_usage +@section GDB usage + +QEMU has a primitive support to work with gdb, so that you can do +'Ctrl-C' while the virtual machine is running and inspect its state. + +In order to use gdb, launch qemu with the '-s' option. It will wait for a +gdb connection: +@example +> qemu -s -kernel arch/i386/boot/bzImage -hda root-2.4.20.img -append "root=/dev/hda" +Connected to host network interface: tun0 +Waiting gdb connection on port 1234 +@end example + +Then launch gdb on the 'vmlinux' executable: +@example +> gdb vmlinux +@end example + +In gdb, connect to QEMU: +@example +(gdb) target remote localhost:1234 +@end example + +Then you can use gdb normally. For example, type 'c' to launch the kernel: +@example +(gdb) c +@end example + +Here are some useful tips in order to use gdb on system code: + +@enumerate +@item +Use @code{info reg} to display all the CPU registers. +@item +Use @code{x/10i $eip} to display the code at the PC position. +@item +Use @code{set architecture i8086} to dump 16 bit code. Then use +@code{x/10i $cs*16+*eip} to dump the code at the PC position. +@end enumerate + +@section Target OS specific information + +@subsection Linux + +To have access to SVGA graphic modes under X11, use the @code{vesa} or +the @code{cirrus} X11 driver. For optimal performances, use 16 bit +color depth in the guest and the host OS. + +When using a 2.6 guest Linux kernel, you should add the option +@code{clock=pit} on the kernel command line because the 2.6 Linux +kernels make very strict real time clock checks by default that QEMU +cannot simulate exactly. + +@subsection Windows + +If you have a slow host, using Windows 95 is better as it gives the +best speed. Windows 2000 is also a good choice. + +@subsubsection SVGA graphic modes support + +QEMU emulates a Cirrus Logic GD5446 Video +card. All Windows versions starting from Windows 95 should recognize +and use this graphic card. For optimal performances, use 16 bit color +depth in the guest and the host OS. + +@subsubsection CPU usage reduction + +Windows 9x does not correctly use the CPU HLT +instruction. The result is that it takes host CPU cycles even when +idle. You can install the utility from +@url{http://www.user.cityline.ru/~maxamn/amnhltm.zip} to solve this +problem. Note that no such tool is needed for NT, 2000 or XP. + +@subsubsection Windows 2000 disk full problems + +Currently (release 0.6.0) QEMU has a bug which gives a @code{disk +full} error during installation of some releases of Windows 2000. The +workaround is to stop QEMU as soon as you notice that your disk image +size is growing too fast (monitor it with @code{ls -ls}). Then +relaunch QEMU to continue the installation. If you still experience +the problem, relaunch QEMU again. + +Future QEMU releases are likely to correct this bug. + +@subsubsection Windows XP security problems + +Some releases of Windows XP install correctly but give a security +error when booting: +@example +A problem is preventing Windows from accurately checking the +license for this computer. Error code: 0x800703e6. +@end example +The only known workaround is to boot in Safe mode +without networking support. + +Future QEMU releases are likely to correct this bug. + +@subsection MS-DOS and FreeDOS + +@subsubsection CPU usage reduction + +DOS does not correctly use the CPU HLT instruction. The result is that +it takes host CPU cycles even when idle. You can install the utility +from @url{http://www.vmware.com/software/dosidle210.zip} to solve this +problem. + +@chapter QEMU PowerPC System emulator invocation + +Use the executable @file{qemu-system-ppc} to simulate a complete PREP +or PowerMac PowerPC system. + +QEMU emulates the following PowerMac peripherials: + +@itemize @minus +@item +UniNorth PCI Bridge +@item +PCI VGA compatible card with VESA Bochs Extensions +@item +2 PMAC IDE interfaces with hard disk and CD-ROM support +@item +NE2000 PCI adapters +@item +Non Volatile RAM +@item +VIA-CUDA with ADB keyboard and mouse. +@end itemize + +QEMU emulates the following PREP peripherials: + +@itemize @minus +@item +PCI Bridge +@item +PCI VGA compatible card with VESA Bochs Extensions +@item +2 IDE interfaces with hard disk and CD-ROM support +@item +Floppy disk +@item +NE2000 network adapters +@item +Serial port +@item +PREP Non Volatile RAM +@item +PC compatible keyboard and mouse. +@end itemize + +QEMU uses the Open Hack'Ware Open Firmware Compatible BIOS available at +@url{http://site.voila.fr/jmayer/OpenHackWare/index.htm}. + +You can read the qemu PC system emulation chapter to have more +informations about QEMU usage. + +@c man begin OPTIONS + +The following options are specific to the PowerPC emulation: + +@table @option + +@item -prep +Simulate a PREP system (default is PowerMAC) + +@item -g WxH[xDEPTH] + +Set the initial VGA graphic mode. The default is 800x600x15. + +@end table + +@c man end + + +More information is available at +@url{http://jocelyn.mayer.free.fr/qemu-ppc/}. + +@chapter QEMU User space emulator invocation + +@section Quick Start + +In order to launch a Linux process, QEMU needs the process executable +itself and all the target (x86) dynamic libraries used by it. + +@itemize + +@item On x86, you can just try to launch any process by using the native +libraries: + +@example +qemu-i386 -L / /bin/ls +@end example + +@code{-L /} tells that the x86 dynamic linker must be searched with a +@file{/} prefix. + +@item Since QEMU is also a linux process, you can launch qemu with qemu (NOTE: you can only do that if you compiled QEMU from the sources): + +@example +qemu-i386 -L / qemu-i386 -L / /bin/ls +@end example + +@item On non x86 CPUs, you need first to download at least an x86 glibc +(@file{qemu-runtime-i386-XXX-.tar.gz} on the QEMU web page). Ensure that +@code{LD_LIBRARY_PATH} is not set: + +@example +unset LD_LIBRARY_PATH +@end example + +Then you can launch the precompiled @file{ls} x86 executable: + +@example +qemu-i386 tests/i386/ls +@end example +You can look at @file{qemu-binfmt-conf.sh} so that +QEMU is automatically launched by the Linux kernel when you try to +launch x86 executables. It requires the @code{binfmt_misc} module in the +Linux kernel. + +@item The x86 version of QEMU is also included. You can try weird things such as: +@example +qemu-i386 /usr/local/qemu-i386/bin/qemu-i386 /usr/local/qemu-i386/bin/ls-i386 +@end example + +@end itemize + +@section Wine launch + +@itemize + +@item Ensure that you have a working QEMU with the x86 glibc +distribution (see previous section). In order to verify it, you must be +able to do: + +@example +qemu-i386 /usr/local/qemu-i386/bin/ls-i386 +@end example + +@item Download the binary x86 Wine install +(@file{qemu-XXX-i386-wine.tar.gz} on the QEMU web page). + +@item Configure Wine on your account. Look at the provided script +@file{/usr/local/qemu-i386/bin/wine-conf.sh}. Your previous +@code{$@{HOME@}/.wine} directory is saved to @code{$@{HOME@}/.wine.org}. + +@item Then you can try the example @file{putty.exe}: + +@example +qemu-i386 /usr/local/qemu-i386/wine/bin/wine /usr/local/qemu-i386/wine/c/Program\ Files/putty.exe +@end example + +@end itemize + +@section Command line options + +@example +usage: qemu-i386 [-h] [-d] [-L path] [-s size] program [arguments...] +@end example + +@table @option +@item -h +Print the help +@item -L path +Set the x86 elf interpreter prefix (default=/usr/local/qemu-i386) +@item -s size +Set the x86 stack size in bytes (default=524288) +@end table + +Debug options: + +@table @option +@item -d +Activate log (logfile=/tmp/qemu.log) +@item -p pagesize +Act as if the host page size was 'pagesize' bytes +@end table + +@node compilation +@chapter Compilation from the sources + +@section Linux/BSD + +Read the @file{README} which gives the related information. + +@section Windows + +@itemize +@item Install the current versions of MSYS and MinGW from +@url{http://www.mingw.org/}. You can find detailed installation +instructions in the download section and the FAQ. + +@item Download +the MinGW development library of SDL 1.2.x +(@file{SDL-devel-1.2.x-mingw32.tar.gz}) from +@url{http://www.libsdl.org}. Unpack it in a temporary place, and +unpack the archive @file{i386-mingw32msvc.tar.gz} in the MinGW tool +directory. Edit the @file{sdl-config} script so that it gives the +correct SDL directory when invoked. + +@item Extract the current version of QEMU. + +@item Start the MSYS shell (file @file{msys.bat}). + +@item Change to the QEMU directory. Launch @file{./configure} and +@file{make}. If you have problems using SDL, verify that +@file{sdl-config} can be launched from the MSYS command line. + +@item You can install QEMU in @file{Program Files/Qemu} by typing +@file{make install}. Don't forget to copy @file{SDL.dll} in +@file{Program Files/Qemu}. + +@end itemize + +@section Cross compilation for Windows with Linux + +@itemize +@item +Install the MinGW cross compilation tools available at +@url{http://www.mingw.org/}. + +@item +Install the Win32 version of SDL (@url{http://www.libsdl.org}) by +unpacking @file{i386-mingw32msvc.tar.gz}. Set up the PATH environment +variable so that @file{i386-mingw32msvc-sdl-config} can be launched by +the QEMU configuration script. + +@item +Configure QEMU for Windows cross compilation: +@example +./configure --enable-mingw32 +@end example +If necessary, you can change the cross-prefix according to the prefix +choosen for the MinGW tools with --cross-prefix. You can also use +--prefix to set the Win32 install path. + +@item You can install QEMU in the installation directory by typing +@file{make install}. Don't forget to copy @file{SDL.dll} in the +installation directory. + +@end itemize + +Note: Currently, Wine does not seem able to launch +QEMU for Win32. + +@section Mac OS X + +The Mac OS X patches are not fully merged in QEMU, so you should look +at the QEMU mailing list archive to have all the necessary +information. + diff --git a/tools/ioemu/qemu-img.c b/tools/ioemu/qemu-img.c new file mode 100644 index 0000000000..132428cf6d --- /dev/null +++ b/tools/ioemu/qemu-img.c @@ -0,0 +1,698 @@ +/* + * create a COW disk image + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +void *get_mmap_addr(unsigned long size) +{ + return NULL; +} + +void qemu_free(void *ptr) +{ + free(ptr); +} + +void *qemu_malloc(size_t size) +{ + return malloc(size); +} + +void *qemu_mallocz(size_t size) +{ + void *ptr; + ptr = qemu_malloc(size); + if (!ptr) + return NULL; + memset(ptr, 0, size); + return ptr; +} + +char *qemu_strdup(const char *str) +{ + char *ptr; + ptr = qemu_malloc(strlen(str) + 1); + if (!ptr) + return NULL; + strcpy(ptr, str); + return ptr; +} + +void pstrcpy(char *buf, int buf_size, const char *str) +{ + int c; + char *q = buf; + + if (buf_size <= 0) + return; + + for(;;) { + c = *str++; + if (c == 0 || q >= buf + buf_size - 1) + break; + *q++ = c; + } + *q = '\0'; +} + +/* strcat and truncate. */ +char *pstrcat(char *buf, int buf_size, const char *s) +{ + int len; + len = strlen(buf); + if (len < buf_size) + pstrcpy(buf + len, buf_size - len, s); + return buf; +} + +int strstart(const char *str, const char *val, const char **ptr) +{ + const char *p, *q; + p = str; + q = val; + while (*q != '\0') { + if (*p != *q) + return 0; + p++; + q++; + } + if (ptr) + *ptr = p; + return 1; +} + +void term_printf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); +} + +void __attribute__((noreturn)) error(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "qemu-img: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + exit(1); + va_end(ap); +} + +static void format_print(void *opaque, const char *name) +{ + printf(" %s", name); +} + +void help(void) +{ + printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004 Fabrice Bellard\n" + "usage: qemu-img command [command options]\n" + "QEMU disk image utility\n" + "\n" + "Command syntax:\n" + " create [-e] [-b base_image] [-f fmt] filename [size]\n" + " commit [-f fmt] filename\n" + " convert [-c] [-e] [-f fmt] filename [-O output_fmt] output_filename\n" + " info [-f fmt] filename\n" + "\n" + "Command parameters:\n" + " 'filename' is a disk image filename\n" + " 'base_image' is the read-only disk image which is used as base for a copy on\n" + " write image; the copy on write image only stores the modified data\n" + " 'fmt' is the disk image format. It is guessed automatically in most cases\n" + " 'size' is the disk image size in kilobytes. Optional suffixes 'M' (megabyte)\n" + " and 'G' (gigabyte) are supported\n" + " 'output_filename' is the destination disk image filename\n" + " 'output_fmt' is the destination format\n" + " '-c' indicates that target image must be compressed (qcow format only)\n" + " '-e' indicates that the target image must be encrypted (qcow format only)\n" + ); + printf("\nSupported format:"); + bdrv_iterate_format(format_print, NULL); + printf("\n"); + exit(1); +} + + +#define NB_SUFFIXES 4 + +static void get_human_readable_size(char *buf, int buf_size, int64_t size) +{ + char suffixes[NB_SUFFIXES] = "KMGT"; + int64_t base; + int i; + + if (size <= 999) { + snprintf(buf, buf_size, "%lld", size); + } else { + base = 1024; + for(i = 0; i < NB_SUFFIXES; i++) { + if (size < (10 * base)) { + snprintf(buf, buf_size, "%0.1f%c", + (double)size / base, + suffixes[i]); + break; + } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) { + snprintf(buf, buf_size, "%lld%c", + (size + (base >> 1)) / base, + suffixes[i]); + break; + } + base = base * 1024; + } + } +} + +#if defined(WIN32) +/* XXX: put correct support for win32 */ +static int read_password(char *buf, int buf_size) +{ + int c, i; + printf("Password: "); + fflush(stdout); + i = 0; + for(;;) { + c = getchar(); + if (c == '\n') + break; + if (i < (buf_size - 1)) + buf[i++] = c; + } + buf[i] = '\0'; + return 0; +} + +#else + +#include + +static struct termios oldtty; + +static void term_exit(void) +{ + tcsetattr (0, TCSANOW, &oldtty); +} + +static void term_init(void) +{ + struct termios tty; + + tcgetattr (0, &tty); + oldtty = tty; + + tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP + |INLCR|IGNCR|ICRNL|IXON); + tty.c_oflag |= OPOST; + tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN); + tty.c_cflag &= ~(CSIZE|PARENB); + tty.c_cflag |= CS8; + tty.c_cc[VMIN] = 1; + tty.c_cc[VTIME] = 0; + + tcsetattr (0, TCSANOW, &tty); + + atexit(term_exit); +} + +int read_password(char *buf, int buf_size) +{ + uint8_t ch; + int i, ret; + + printf("password: "); + fflush(stdout); + term_init(); + i = 0; + for(;;) { + ret = read(0, &ch, 1); + if (ret == -1) { + if (errno == EAGAIN || errno == EINTR) { + continue; + } else { + ret = -1; + break; + } + } else if (ret == 0) { + ret = -1; + break; + } else { + if (ch == '\r') { + ret = 0; + break; + } + if (i < (buf_size - 1)) + buf[i++] = ch; + } + } + term_exit(); + buf[i] = '\0'; + printf("\n"); + return ret; +} +#endif + +static BlockDriverState *bdrv_new_open(const char *filename, + const char *fmt) +{ + BlockDriverState *bs; + BlockDriver *drv; + char password[256]; + + bs = bdrv_new(""); + if (!bs) + error("Not enough memory"); + if (fmt) { + drv = bdrv_find_format(fmt); + if (!drv) + error("Unknown file format '%s'", fmt); + } else { + drv = NULL; + } + if (bdrv_open2(bs, filename, 0, drv) < 0) { + error("Could not open '%s'", filename); + } + if (bdrv_is_encrypted(bs)) { + printf("Disk image '%s' is encrypted.\n", filename); + if (read_password(password, sizeof(password)) < 0) + error("No password given"); + if (bdrv_set_key(bs, password) < 0) + error("invalid password"); + } + return bs; +} + +static int img_create(int argc, char **argv) +{ + int c, ret, encrypted; + const char *fmt = "raw"; + const char *filename; + const char *base_filename = NULL; + int64_t size; + const char *p; + BlockDriver *drv; + + encrypted = 0; + for(;;) { + c = getopt(argc, argv, "b:f:he"); + if (c == -1) + break; + switch(c) { + case 'h': + help(); + break; + case 'b': + base_filename = optarg; + break; + case 'f': + fmt = optarg; + break; + case 'e': + encrypted = 1; + break; + } + } + if (optind >= argc) + help(); + filename = argv[optind++]; + size = 0; + if (base_filename) { + BlockDriverState *bs; + bs = bdrv_new_open(base_filename, NULL); + bdrv_get_geometry(bs, &size); + size *= 512; + bdrv_delete(bs); + } else { + if (optind >= argc) + help(); + p = argv[optind]; + size = strtoul(p, (char **)&p, 0); + if (*p == 'M') { + size *= 1024 * 1024; + } else if (*p == 'G') { + size *= 1024 * 1024 * 1024; + } else if (*p == 'k' || *p == 'K' || *p == '\0') { + size *= 1024; + } else { + help(); + } + } + drv = bdrv_find_format(fmt); + if (!drv) + error("Unknown file format '%s'", fmt); + printf("Formating '%s', fmt=%s", + filename, fmt); + if (encrypted) + printf(", encrypted"); + if (base_filename) { + printf(", backing_file=%s", + base_filename); + } + printf(", size=%lld kB\n", size / 1024); + ret = bdrv_create(drv, filename, size / 512, base_filename, encrypted); + if (ret < 0) { + if (ret == -ENOTSUP) { + error("Formatting or formatting option not supported for file format '%s'", fmt); + } else { + error("Error while formatting"); + } + } + return 0; +} + +static int img_commit(int argc, char **argv) +{ + int c, ret; + const char *filename, *fmt; + BlockDriver *drv; + BlockDriverState *bs; + + fmt = NULL; + for(;;) { + c = getopt(argc, argv, "f:h"); + if (c == -1) + break; + switch(c) { + case 'h': + help(); + break; + case 'f': + fmt = optarg; + break; + } + } + if (optind >= argc) + help(); + filename = argv[optind++]; + + bs = bdrv_new(""); + if (!bs) + error("Not enough memory"); + if (fmt) { + drv = bdrv_find_format(fmt); + if (!drv) + error("Unknown file format '%s'", fmt); + } else { + drv = NULL; + } + if (bdrv_open2(bs, filename, 0, drv) < 0) { + error("Could not open '%s'", filename); + } + ret = bdrv_commit(bs); + switch(ret) { + case 0: + printf("Image committed.\n"); + break; + case -ENOENT: + error("No disk inserted"); + break; + case -EACCES: + error("Image is read-only"); + break; + case -ENOTSUP: + error("Image is already committed"); + break; + default: + error("Error while committing image"); + break; + } + + bdrv_delete(bs); + return 0; +} + +static int is_not_zero(const uint8_t *sector, int len) +{ + int i; + len >>= 2; + for(i = 0;i < len; i++) { + if (((uint32_t *)sector)[i] != 0) + return 1; + } + return 0; +} + +static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum) +{ + int v, i; + + if (n <= 0) { + *pnum = 0; + return 0; + } + v = is_not_zero(buf, 512); + for(i = 1; i < n; i++) { + buf += 512; + if (v != is_not_zero(buf, 512)) + break; + } + *pnum = i; + return v; +} + +#define IO_BUF_SIZE 65536 + +static int img_convert(int argc, char **argv) +{ + int c, ret, n, n1, compress, cluster_size, cluster_sectors, encrypt; + const char *filename, *fmt, *out_fmt, *out_filename; + BlockDriver *drv; + BlockDriverState *bs, *out_bs; + int64_t total_sectors, nb_sectors, sector_num; + uint8_t buf[IO_BUF_SIZE]; + const uint8_t *buf1; + + fmt = NULL; + out_fmt = "raw"; + compress = 0; + encrypt = 0; + for(;;) { + c = getopt(argc, argv, "f:O:hce"); + if (c == -1) + break; + switch(c) { + case 'h': + help(); + break; + case 'f': + fmt = optarg; + break; + case 'O': + out_fmt = optarg; + break; + case 'c': + compress = 1; + break; + case 'e': + encrypt = 1; + break; + } + } + if (optind >= argc) + help(); + filename = argv[optind++]; + if (optind >= argc) + help(); + out_filename = argv[optind++]; + + bs = bdrv_new_open(filename, fmt); + + drv = bdrv_find_format(out_fmt); + if (!drv) + error("Unknown file format '%s'", fmt); + if (compress && drv != &bdrv_qcow) + error("Compression not supported for this file format"); + if (encrypt && drv != &bdrv_qcow) + error("Encryption not supported for this file format"); + if (compress && encrypt) + error("Compression and encryption not supported at the same time"); + bdrv_get_geometry(bs, &total_sectors); + ret = bdrv_create(drv, out_filename, total_sectors, NULL, encrypt); + if (ret < 0) { + if (ret == -ENOTSUP) { + error("Formatting not supported for file format '%s'", fmt); + } else { + error("Error while formatting '%s'", out_filename); + } + } + + out_bs = bdrv_new_open(out_filename, out_fmt); + + if (compress) { + cluster_size = qcow_get_cluster_size(out_bs); + if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) + error("invalid cluster size"); + cluster_sectors = cluster_size >> 9; + sector_num = 0; + for(;;) { + nb_sectors = total_sectors - sector_num; + if (nb_sectors <= 0) + break; + if (nb_sectors >= cluster_sectors) + n = cluster_sectors; + else + n = nb_sectors; + if (bdrv_read(bs, sector_num, buf, n) < 0) + error("error while reading"); + if (n < cluster_sectors) + memset(buf + n * 512, 0, cluster_size - n * 512); + if (is_not_zero(buf, cluster_size)) { + if (qcow_compress_cluster(out_bs, sector_num, buf) != 0) + error("error while compressing sector %lld", sector_num); + } + sector_num += n; + } + } else { + sector_num = 0; + for(;;) { + nb_sectors = total_sectors - sector_num; + if (nb_sectors <= 0) + break; + if (nb_sectors >= (IO_BUF_SIZE / 512)) + n = (IO_BUF_SIZE / 512); + else + n = nb_sectors; + if (bdrv_read(bs, sector_num, buf, n) < 0) + error("error while reading"); + /* NOTE: at the same time we convert, we do not write zero + sectors to have a chance to compress the image. Ideally, we + should add a specific call to have the info to go faster */ + buf1 = buf; + while (n > 0) { + if (is_allocated_sectors(buf1, n, &n1)) { + if (bdrv_write(out_bs, sector_num, buf1, n1) < 0) + error("error while writing"); + } + sector_num += n1; + n -= n1; + buf1 += n1 * 512; + } + } + } + bdrv_delete(out_bs); + bdrv_delete(bs); + return 0; +} + +#ifdef _WIN32 +static int64_t get_allocated_file_size(const char *filename) +{ + struct _stati64 st; + if (_stati64(filename, &st) < 0) + return -1; + return st.st_size; +} +#else +static int64_t get_allocated_file_size(const char *filename) +{ + struct stat st; + if (stat(filename, &st) < 0) + return -1; + return (int64_t)st.st_blocks * 512; +} +#endif + +static int img_info(int argc, char **argv) +{ + int c; + const char *filename, *fmt; + BlockDriver *drv; + BlockDriverState *bs; + char fmt_name[128], size_buf[128], dsize_buf[128]; + int64_t total_sectors, allocated_size; + + fmt = NULL; + for(;;) { + c = getopt(argc, argv, "f:h"); + if (c == -1) + break; + switch(c) { + case 'h': + help(); + break; + case 'f': + fmt = optarg; + break; + } + } + if (optind >= argc) + help(); + filename = argv[optind++]; + + bs = bdrv_new(""); + if (!bs) + error("Not enough memory"); + if (fmt) { + drv = bdrv_find_format(fmt); + if (!drv) + error("Unknown file format '%s'", fmt); + } else { + drv = NULL; + } + if (bdrv_open2(bs, filename, 0, drv) < 0) { + error("Could not open '%s'", filename); + } + bdrv_get_format(bs, fmt_name, sizeof(fmt_name)); + bdrv_get_geometry(bs, &total_sectors); + get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512); + allocated_size = get_allocated_file_size(filename); + if (allocated_size < 0) + error("Could not get file size '%s'", filename); + get_human_readable_size(dsize_buf, sizeof(dsize_buf), + allocated_size); + printf("image: %s\n" + "file format: %s\n" + "virtual size: %s (%lld bytes)\n" + "disk size: %s\n", + filename, fmt_name, size_buf, + total_sectors * 512, + dsize_buf); + if (bdrv_is_encrypted(bs)) + printf("encrypted: yes\n"); + bdrv_delete(bs); + return 0; +} + +int main(int argc, char **argv) +{ + const char *cmd; + + bdrv_init(); + if (argc < 2) + help(); + cmd = argv[1]; + optind++; + if (!strcmp(cmd, "create")) { + img_create(argc, argv); + } else if (!strcmp(cmd, "commit")) { + img_commit(argc, argv); + } else if (!strcmp(cmd, "convert")) { + img_convert(argc, argv); + } else if (!strcmp(cmd, "info")) { + img_info(argc, argv); + } else { + help(); + } + return 0; +} diff --git a/tools/ioemu/qemu-mkcow.1 b/tools/ioemu/qemu-mkcow.1 new file mode 100644 index 0000000000..d156de6fbb --- /dev/null +++ b/tools/ioemu/qemu-mkcow.1 @@ -0,0 +1,105 @@ +.\" $Header: /cvsroot/qemu/qemu/qemu-mkcow.1,v 1.1 2004/03/26 22:42:54 bellard Exp $ +.\" +.\" transcript compatibility for postscript use. +.\" +.\" synopsis: .P! +.\" +.de P! +.fl +\!!1 setgray +.fl +\\&.\" +.fl +\!!0 setgray +.fl \" force out current output buffer +\!!save /psv exch def currentpoint translate 0 0 moveto +\!!/showpage{}def +.fl \" prolog +.sy sed -e 's/^/!/' \\$1\" bring in postscript file +\!!psv restore +. +.de pF +.ie \\*(f1 .ds f1 \\n(.f +.el .ie \\*(f2 .ds f2 \\n(.f +.el .ie \\*(f3 .ds f3 \\n(.f +.el .ie \\*(f4 .ds f4 \\n(.f +.el .tm ? font overflow +.ft \\$1 +.. +.de fP +.ie !\\*(f4 \{\ +. ft \\*(f4 +. ds f4\" +' br \} +.el .ie !\\*(f3 \{\ +. ft \\*(f3 +. ds f3\" +' br \} +.el .ie !\\*(f2 \{\ +. ft \\*(f2 +. ds f2\" +' br \} +.el .ie !\\*(f1 \{\ +. ft \\*(f1 +. ds f1\" +' br \} +.el .tm ? font underflow +.. +.ds f1\" +.ds f2\" +.ds f3\" +.ds f4\" +'\" t +.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n +.TH "QEMU" "8" +.SH "NAME" +qemu-mkcow \(em create a copy-on-write file for qemu +.SH "SYNOPSIS" +.PP +\fBqemu-mkcow\fR [\fB-h\fP] [\fB-f \fImaster_disk_image\fR\fP] [\fIcow_image\fR] [\fB\fIcow_size\fR\fP] +.SH "DESCRIPTION" +.PP +The \fBqemu-mkcow\fR command creates a +persistent copy-on-write file for \fBqemu\fR. + +.PP +\fBqemu\fR can be used in a "copy-on-write" mode, +where changes made by \fBqemu\fR do not actually +change the disk image file. One way is to invoke +\fBqemu\fR with -snapshot: these changes +are stored in a temporary file, which is discarded when +\fBqemu\fR exits. + +.PP +\fBqemu-mkcow\fR creates an explicit copy-on-write +file where changes are to be stored: this way, changes made +inside \fBqemu\fR will still be there next time you +run it, although the master disk image isn't ever changed. + +.PP +The usual method is to create the master image, then create a +copy-on-write file using \fBqemu-mkcow\fR with +\fB-f\fP. The filename of the master image is stored +inside the generated copy-on-write file: it must not be modified +after this is run! + +.PP +If no master file is specified, the effect is that of a +blank master of size \fIcow_size\fR. + +.SH "SEE ALSO" +.PP +qemu(1), qemu-fast(1). +.SH "AUTHOR" +.PP +This manual page was written by Paul Russell prussell@debian.org for +the \fBDebian\fP system (but may be used by others). Permission is +granted to copy, distribute and/or modify this document under +the terms of the GNU General Public License, Version 2 any +later version published by the Free Software Foundation. + +.PP +On Debian systems, the complete text of the GNU General Public +License can be found in /usr/share/common-licenses/GPL. + +.\" created by instant / docbook-to-man, Fri 12 Mar 2004, 05:58 diff --git a/tools/ioemu/qemu-tech.html b/tools/ioemu/qemu-tech.html new file mode 100644 index 0000000000..4277cfed1b --- /dev/null +++ b/tools/ioemu/qemu-tech.html @@ -0,0 +1,1303 @@ + + + + + +Untitled Document: + + + + + + + + + + + + + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

+ +

1. Introduction

+ +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

1.1 Features

+ +

+ +QEMU is a FAST! processor emulator using a portable dynamic +translator. +

+ +QEMU has two operating modes: +

+ +

    + +
  • +Full system emulation. In this mode, QEMU emulates a full system +(usually a PC), including a processor and various peripherials. It can +be used to launch an different Operating System without rebooting the +PC or to debug system code. +

    + +

  • +User mode emulation (Linux host only). In this mode, QEMU can launch +Linux processes compiled for one CPU on another CPU. It can be used to +launch the Wine Windows API emulator (http://www.winehq.org) or +to ease cross-compilation and cross-debugging. +

    + +

+

+ +As QEMU requires no host kernel driver to run, it is very safe and +easy to use. +

+ +QEMU generic features: +

+ +

    + +
  • User space only or full system emulation. +

    + +

  • Using dynamic translation to native code for reasonnable speed. +

    + +

  • Working on x86 and PowerPC hosts. Being tested on ARM, Sparc32, Alpha and S390. +

    + +

  • Self-modifying code support. +

    + +

  • Precise exceptions support. +

    + +

  • The virtual CPU is a library (libqemu) which can be used +in other projects (look at `qemu/tests/qruncom.c' to have an +example of user mode libqemu usage). +

    + +

+

+ +QEMU user mode emulation features: +

    +
  • Generic Linux system call converter, including most ioctls. +

    + +

  • clone() emulation using native CPU clone() to use Linux scheduler for threads. +

    + +

  • Accurate signal handling by remapping host signals to target signals. +
+ + +QEMU full system emulation features: +
    +
  • QEMU can either use a full software MMU for maximum portability or use the host system call mmap() to simulate the target MMU. +
+ +
+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

1.2 x86 emulation

+ +

+ +QEMU x86 target features: +

+ +

    + +
  • The virtual x86 CPU supports 16 bit and 32 bit addressing with segmentation. +LDT/GDT and IDT are emulated. VM86 mode is also supported to run DOSEMU. +

    + +

  • Support of host page sizes bigger than 4KB in user mode emulation. +

    + +

  • QEMU can emulate itself on x86. +

    + +

  • An extensive Linux x86 CPU test program is included `tests/test-i386'. +It can be used to test other x86 virtual CPUs. +

    + +

+

+ +Current QEMU limitations: +

+ +

    + +
  • No SSE/MMX support (yet). +

    + +

  • No x86-64 support. +

    + +

  • IPC syscalls are missing. +

    + +

  • The x86 segment limits and access rights are not tested at every +memory access (yet). Hopefully, very few OSes seem to rely on that for +normal use. +

    + +

  • On non x86 host CPUs, doubles are used instead of the non standard +10 byte long doubles of x86 for floating point emulation to get +maximum performances. +

    + +

+

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

1.3 ARM emulation

+ +

+ +

    + +
  • Full ARM 7 user emulation. +

    + +

  • NWFPE FPU support included in user Linux emulation. +

    + +

  • Can run most ARM Linux binaries. +

    + +

+

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

1.4 PowerPC emulation

+ +

+ +

    + +
  • Full PowerPC 32 bit emulation, including priviledged instructions, +FPU and MMU. +

    + +

  • Can run most PowerPC Linux binaries. +

    + +

+

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

1.5 SPARC emulation

+ +

+ +

    + +
  • SPARC V8 user support, except FPU instructions. +

    + +

  • Can run some SPARC Linux binaries. +

    + +

+

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2. QEMU Internals

+ +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.1 QEMU compared to other emulators

+ +

+ +Like bochs [3], QEMU emulates an x86 CPU. But QEMU is much faster than +bochs as it uses dynamic compilation. Bochs is closely tied to x86 PC +emulation while QEMU can emulate several processors. +

+ +Like Valgrind [2], QEMU does user space emulation and dynamic +translation. Valgrind is mainly a memory debugger while QEMU has no +support for it (QEMU could be used to detect out of bound memory +accesses as Valgrind, but it has no support to track uninitialised data +as Valgrind does). The Valgrind dynamic translator generates better code +than QEMU (in particular it does register allocation) but it is closely +tied to an x86 host and target and has no support for precise exceptions +and system emulation. +

+ +EM86 [4] is the closest project to user space QEMU (and QEMU still uses +some of its code, in particular the ELF file loader). EM86 was limited +to an alpha host and used a proprietary and slow interpreter (the +interpreter part of the FX!32 Digital Win32 code translator [5]). +

+ +TWIN [6] is a Windows API emulator like Wine. It is less accurate than +Wine but includes a protected mode x86 interpreter to launch x86 Windows +executables. Such an approach has greater potential because most of the +Windows API is executed natively but it is far more difficult to develop +because all the data structures and function parameters exchanged +between the API and the x86 code must be converted. +

+ +User mode Linux [7] was the only solution before QEMU to launch a +Linux kernel as a process while not needing any host kernel +patches. However, user mode Linux requires heavy kernel patches while +QEMU accepts unpatched Linux kernels. The price to pay is that QEMU is +slower. +

+ +The new Plex86 [8] PC virtualizer is done in the same spirit as the +qemu-fast system emulator. It requires a patched Linux kernel to work +(you cannot launch the same kernel on your PC), but the patches are +really small. As it is a PC virtualizer (no emulation is done except +for some priveledged instructions), it has the potential of being +faster than QEMU. The downside is that a complicated (and potentially +unsafe) host kernel patch is needed. +

+ +The commercial PC Virtualizers (VMWare [9], VirtualPC [10], TwoOStwo +[11]) are faster than QEMU, but they all need specific, proprietary +and potentially unsafe host drivers. Moreover, they are unable to +provide cycle exact simulation as an emulator can. +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.2 Portable dynamic translation

+ +

+ +QEMU is a dynamic translator. When it first encounters a piece of code, +it converts it to the host instruction set. Usually dynamic translators +are very complicated and highly CPU dependent. QEMU uses some tricks +which make it relatively easily portable and simple while achieving good +performances. +

+ +The basic idea is to split every x86 instruction into fewer simpler +instructions. Each simple instruction is implemented by a piece of C +code (see `target-i386/op.c'). Then a compile time tool +(`dyngen') takes the corresponding object file (`op.o') +to generate a dynamic code generator which concatenates the simple +instructions to build a function (see `op.h:dyngen_code()'). +

+ +In essence, the process is similar to [1], but more work is done at +compile time. +

+ +A key idea to get optimal performances is that constant parameters can +be passed to the simple operations. For that purpose, dummy ELF +relocations are generated with gcc for each constant parameter. Then, +the tool (`dyngen') can locate the relocations and generate the +appriopriate C code to resolve them when building the dynamic code. +

+ +That way, QEMU is no more difficult to port than a dynamic linker. +

+ +To go even faster, GCC static register variables are used to keep the +state of the virtual CPU. +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.3 Register allocation

+ +

+ +Since QEMU uses fixed simple instructions, no efficient register +allocation can be done. However, because RISC CPUs have a lot of +register, most of the virtual CPU state can be put in registers without +doing complicated register allocation. +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.4 Condition code optimisations

+ +

+ +Good CPU condition codes emulation (EFLAGS register on x86) is a +critical point to get good performances. QEMU uses lazy condition code +evaluation: instead of computing the condition codes after each x86 +instruction, it just stores one operand (called CC_SRC), the +result (called CC_DST) and the type of operation (called +CC_OP). +

+ +CC_OP is almost never explicitely set in the generated code +because it is known at translation time. +

+ +In order to increase performances, a backward pass is performed on the +generated simple instructions (see +target-i386/translate.c:optimize_flags()). When it can be proved that +the condition codes are not needed by the next instructions, no +condition codes are computed at all. +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.5 CPU state optimisations

+ +

+ +The x86 CPU has many internal states which change the way it evaluates +instructions. In order to achieve a good speed, the translation phase +considers that some state information of the virtual x86 CPU cannot +change in it. For example, if the SS, DS and ES segments have a zero +base, then the translator does not even generate an addition for the +segment base. +

+ +[The FPU stack pointer register is not handled that way yet]. +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.6 Translation cache

+ +

+ +A 16 MByte cache holds the most recently used translations. For +simplicity, it is completely flushed when it is full. A translation unit +contains just a single basic block (a block of x86 instructions +terminated by a jump or by a virtual CPU state change which the +translator cannot deduce statically). +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.7 Direct block chaining

+ +

+ +After each translated basic block is executed, QEMU uses the simulated +Program Counter (PC) and other cpu state informations (such as the CS +segment base value) to find the next basic block. +

+ +In order to accelerate the most common cases where the new simulated PC +is known, QEMU can patch a basic block so that it jumps directly to the +next one. +

+ +The most portable code uses an indirect jump. An indirect jump makes +it easier to make the jump target modification atomic. On some host +architectures (such as x86 or PowerPC), the JUMP opcode is +directly patched so that the block chaining has no overhead. +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.8 Self-modifying code and translated code invalidation

+ +

+ +Self-modifying code is a special challenge in x86 emulation because no +instruction cache invalidation is signaled by the application when code +is modified. +

+ +When translated code is generated for a basic block, the corresponding +host page is write protected if it is not already read-only (with the +system call mprotect()). Then, if a write access is done to the +page, Linux raises a SEGV signal. QEMU then invalidates all the +translated code in the page and enables write accesses to the page. +

+ +Correct translated code invalidation is done efficiently by maintaining +a linked list of every translated block contained in a given page. Other +linked lists are also maintained to undo direct block chaining. +

+ +Although the overhead of doing mprotect() calls is important, +most MSDOS programs can be emulated at reasonnable speed with QEMU and +DOSEMU. +

+ +Note that QEMU also invalidates pages of translated code when it detects +that memory mappings are modified with mmap() or munmap(). +

+ +When using a software MMU, the code invalidation is more efficient: if +a given code page is invalidated too often because of write accesses, +then a bitmap representing all the code inside the page is +built. Every store into that page checks the bitmap to see if the code +really needs to be invalidated. It avoids invalidating the code when +only data is modified in the page. +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.9 Exception support

+ +

+ +longjmp() is used when an exception such as division by zero is +encountered. +

+ +The host SIGSEGV and SIGBUS signal handlers are used to get invalid +memory accesses. The exact CPU state can be retrieved because all the +x86 registers are stored in fixed host registers. The simulated program +counter is found by retranslating the corresponding basic block and by +looking where the host program counter was at the exception point. +

+ +The virtual CPU cannot retrieve the exact EFLAGS register because +in some cases it is not computed because of condition code +optimisations. It is not a big concern because the emulated code can +still be restarted in any cases. +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.10 MMU emulation

+ +

+ +For system emulation, QEMU uses the mmap() system call to emulate the +target CPU MMU. It works as long the emulated OS does not use an area +reserved by the host OS (such as the area above 0xc0000000 on x86 +Linux). +

+ +In order to be able to launch any OS, QEMU also supports a soft +MMU. In that mode, the MMU virtual to physical address translation is +done at every memory access. QEMU uses an address translation cache to +speed up the translation. +

+ +In order to avoid flushing the translated code each time the MMU +mappings change, QEMU uses a physically indexed translation cache. It +means that each basic block is indexed with its physical address. +

+ +When MMU mappings change, only the chaining of the basic blocks is +reset (i.e. a basic block can no longer jump directly to another one). +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.11 Hardware interrupts

+ +

+ +In order to be faster, QEMU does not check at every basic block if an +hardware interrupt is pending. Instead, the user must asynchrously +call a specific function to tell that an interrupt is pending. This +function resets the chaining of the currently executing basic +block. It ensures that the execution will return soon in the main loop +of the CPU emulator. Then the main loop can test if the interrupt is +pending and handle it. +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.12 User emulation specific details

+ +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.12.1 Linux system call translation

+ +

+ +QEMU includes a generic system call translator for Linux. It means that +the parameters of the system calls can be converted to fix the +endianness and 32/64 bit issues. The IOCTLs are converted with a generic +type description system (see `ioctls.h' and `thunk.c'). +

+ +QEMU supports host CPUs which have pages bigger than 4KB. It records all +the mappings the process does and try to emulated the mmap() +system calls in cases where the host mmap() call would fail +because of bad page alignment. +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.12.2 Linux signals

+ +

+ +Normal and real-time signals are queued along with their information +(siginfo_t) as it is done in the Linux kernel. Then an interrupt +request is done to the virtual CPU. When it is interrupted, one queued +signal is handled by generating a stack frame in the virtual CPU as the +Linux kernel does. The sigreturn() system call is emulated to return +from the virtual signal handler. +

+ +Some signals (such as SIGALRM) directly come from the host. Other +signals are synthetized from the virtual CPU exceptions such as SIGFPE +when a division by zero is done (see main.c:cpu_loop()). +

+ +The blocked signal mask is still handled by the host Linux kernel so +that most signal system calls can be redirected directly to the host +Linux kernel. Only the sigaction() and sigreturn() system +calls need to be fully emulated (see `signal.c'). +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.12.3 clone() system call and threads

+ +

+ +The Linux clone() system call is usually used to create a thread. QEMU +uses the host clone() system call so that real host threads are created +for each emulated thread. One virtual CPU instance is created for each +thread. +

+ +The virtual x86 CPU atomic operations are emulated with a global lock so +that their semantic is preserved. +

+ +Note that currently there are still some locking issues in QEMU. In +particular, the translated cache flush is not protected yet against +reentrancy. +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.12.4 Self-virtualization

+ +

+ +QEMU was conceived so that ultimately it can emulate itself. Although +it is not very useful, it is an important test to show the power of the +emulator. +

+ +Achieving self-virtualization is not easy because there may be address +space conflicts. QEMU solves this problem by being an executable ELF +shared object as the ld-linux.so ELF interpreter. That way, it can be +relocated at load time. +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

2.13 Bibliography

+ +

+ +

+ +
[1] +
http://citeseer.nj.nec.com/piumarta98optimizing.html, Optimizing +direct threaded code by selective inlining (1998) by Ian Piumarta, Fabio +Riccardi. +

+ +

[2] +
http://developer.kde.org/~sewardj/, Valgrind, an open-source +memory debugger for x86-GNU/Linux, by Julian Seward. +

+ +

[3] +
http://bochs.sourceforge.net/, the Bochs IA-32 Emulator Project, +by Kevin Lawton et al. +

+ +

[4] +
http://www.cs.rose-hulman.edu/~donaldlf/em86/index.html, the EM86 +x86 emulator on Alpha-Linux. +

+ +

[5] +
http://www.usenix.org/publications/library/proceedings/usenix-nt97/full_papers/chernoff/chernoff.pdf, +DIGITAL FX!32: Running 32-Bit x86 Applications on Alpha NT, by Anton +Chernoff and Ray Hookway. +

+ +

[6] +
http://www.willows.com/, Windows API library emulation from +Willows Software. +

+ +

[7] +
http://user-mode-linux.sourceforge.net/, +The User-mode Linux Kernel. +

+ +

[8] +
http://www.plex86.org/, +The new Plex86 project. +

+ +

[9] +
http://www.vmware.com/, +The VMWare PC virtualizer. +

+ +

[10] +
http://www.microsoft.com/windowsxp/virtualpc/, +The VirtualPC PC virtualizer. +

+ +

[11] +
http://www.twoostwo.org/, +The TwoOStwo PC virtualizer. +

+ +

+

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

3. Regression Tests

+ +

+ +In the directory `tests/', various interesting testing programs +are available. There are used for regression testing. +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

3.1 `test-i386'

+ +

+ +This program executes most of the 16 bit and 32 bit x86 instructions and +generates a text output. It can be compared with the output obtained with +a real CPU or another emulator. The target make test runs this +program and a diff on the generated output. +

+ +The Linux system call modify_ldt() is used to create x86 selectors +to test some 16 bit addressing and 32 bit with segmentation cases. +

+ +The Linux system call vm86() is used to test vm86 emulation. +

+ +Various exceptions are raised to test most of the x86 user space +exception reporting. +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

3.2 `linux-test'

+ +

+ +This program tests various Linux system calls. It is used to verify +that the system call parameters are correctly converted between target +and host CPUs. +

+ +


+ + + + + + + + + + + +
[ < ][ > ]   [ << ][ Up ][ >> ]         [Top][Contents][Index][ ? ]
+

3.3 `qruncom.c'

+ +

+ +Example of usage of libqemu to emulate a user mode i386 CPU. +


+ + + + + + +
[Top][Contents][Index][ ? ]
+

Table of Contents

+ +
+ + + + + + +
[Top][Contents][Index][ ? ]
+

Short Table of Contents

+
+1. Introduction +
+2. QEMU Internals +
+3. Regression Tests +
+ +
+
+ + + + + + +
[Top][Contents][Index][ ? ]
+

About this document

+This document was generated on January, 25 2005 +using texi2html +

+The buttons in the navigation panels have the following meaning: +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Button Name Go to From 1.2.3 go to
+ [ < ] +Back + +previous section in reading order + +1.2.2 +
+ [ > ] +Forward + +next section in reading order + +1.2.4 +
+ [ << ] +FastBack + +previous or up-and-previous section + +1.1 +
+ [ Up ] +Up + +up section + +1.2 +
+ [ >> ] +FastForward + +next or up-and-next section + +1.3 +
+ [Top] +Top + +cover (top) of document + +   +
+ [Contents] +Contents + +table of contents + +   +
+ [Index] +Index + +concept index + +   +
+ [ ? ] +About + +this page + +   +
+

+where the Example assumes that the current position +is at Subsubsection One-Two-Three of a document of +the following structure: +
    +
  • 1. Section One
  • +
      +
    • 1.1 Subsection One-One
    • +
        +
      • ...
      • +
      +
    • 1.2 Subsection One-Two
    • +
        +
      • 1.2.1 Subsubsection One-Two-One +
      • 1.2.2 Subsubsection One-Two-Two +
      • 1.2.3 Subsubsection One-Two-Three     +<== Current Position +
      • 1.2.4 Subsubsection One-Two-Four +
      +
    • 1.3 Subsection One-Three
    • +
        +
      • ...
      • +
      +
    • 1.4 Subsection One-Four
    • +
    +
+ +
+
+ +This document was generated +on January, 25 2005 +using texi2html + + + diff --git a/tools/ioemu/qemu-tech.texi b/tools/ioemu/qemu-tech.texi new file mode 100644 index 0000000000..4e6f507c74 --- /dev/null +++ b/tools/ioemu/qemu-tech.texi @@ -0,0 +1,494 @@ +\input texinfo @c -*- texinfo -*- + +@iftex +@settitle QEMU Internals +@titlepage +@sp 7 +@center @titlefont{QEMU Internals} +@sp 3 +@end titlepage +@end iftex + +@chapter Introduction + +@section Features + +QEMU is a FAST! processor emulator using a portable dynamic +translator. + +QEMU has two operating modes: + +@itemize @minus + +@item +Full system emulation. In this mode, QEMU emulates a full system +(usually a PC), including a processor and various peripherials. It can +be used to launch an different Operating System without rebooting the +PC or to debug system code. + +@item +User mode emulation (Linux host only). In this mode, QEMU can launch +Linux processes compiled for one CPU on another CPU. It can be used to +launch the Wine Windows API emulator (@url{http://www.winehq.org}) or +to ease cross-compilation and cross-debugging. + +@end itemize + +As QEMU requires no host kernel driver to run, it is very safe and +easy to use. + +QEMU generic features: + +@itemize + +@item User space only or full system emulation. + +@item Using dynamic translation to native code for reasonnable speed. + +@item Working on x86 and PowerPC hosts. Being tested on ARM, Sparc32, Alpha and S390. + +@item Self-modifying code support. + +@item Precise exceptions support. + +@item The virtual CPU is a library (@code{libqemu}) which can be used +in other projects (look at @file{qemu/tests/qruncom.c} to have an +example of user mode @code{libqemu} usage). + +@end itemize + +QEMU user mode emulation features: +@itemize +@item Generic Linux system call converter, including most ioctls. + +@item clone() emulation using native CPU clone() to use Linux scheduler for threads. + +@item Accurate signal handling by remapping host signals to target signals. +@end itemize +@end itemize + +QEMU full system emulation features: +@itemize +@item QEMU can either use a full software MMU for maximum portability or use the host system call mmap() to simulate the target MMU. +@end itemize + +@section x86 emulation + +QEMU x86 target features: + +@itemize + +@item The virtual x86 CPU supports 16 bit and 32 bit addressing with segmentation. +LDT/GDT and IDT are emulated. VM86 mode is also supported to run DOSEMU. + +@item Support of host page sizes bigger than 4KB in user mode emulation. + +@item QEMU can emulate itself on x86. + +@item An extensive Linux x86 CPU test program is included @file{tests/test-i386}. +It can be used to test other x86 virtual CPUs. + +@end itemize + +Current QEMU limitations: + +@itemize + +@item No SSE/MMX support (yet). + +@item No x86-64 support. + +@item IPC syscalls are missing. + +@item The x86 segment limits and access rights are not tested at every +memory access (yet). Hopefully, very few OSes seem to rely on that for +normal use. + +@item On non x86 host CPUs, @code{double}s are used instead of the non standard +10 byte @code{long double}s of x86 for floating point emulation to get +maximum performances. + +@end itemize + +@section ARM emulation + +@itemize + +@item Full ARM 7 user emulation. + +@item NWFPE FPU support included in user Linux emulation. + +@item Can run most ARM Linux binaries. + +@end itemize + +@section PowerPC emulation + +@itemize + +@item Full PowerPC 32 bit emulation, including priviledged instructions, +FPU and MMU. + +@item Can run most PowerPC Linux binaries. + +@end itemize + +@section SPARC emulation + +@itemize + +@item SPARC V8 user support, except FPU instructions. + +@item Can run some SPARC Linux binaries. + +@end itemize + +@chapter QEMU Internals + +@section QEMU compared to other emulators + +Like bochs [3], QEMU emulates an x86 CPU. But QEMU is much faster than +bochs as it uses dynamic compilation. Bochs is closely tied to x86 PC +emulation while QEMU can emulate several processors. + +Like Valgrind [2], QEMU does user space emulation and dynamic +translation. Valgrind is mainly a memory debugger while QEMU has no +support for it (QEMU could be used to detect out of bound memory +accesses as Valgrind, but it has no support to track uninitialised data +as Valgrind does). The Valgrind dynamic translator generates better code +than QEMU (in particular it does register allocation) but it is closely +tied to an x86 host and target and has no support for precise exceptions +and system emulation. + +EM86 [4] is the closest project to user space QEMU (and QEMU still uses +some of its code, in particular the ELF file loader). EM86 was limited +to an alpha host and used a proprietary and slow interpreter (the +interpreter part of the FX!32 Digital Win32 code translator [5]). + +TWIN [6] is a Windows API emulator like Wine. It is less accurate than +Wine but includes a protected mode x86 interpreter to launch x86 Windows +executables. Such an approach has greater potential because most of the +Windows API is executed natively but it is far more difficult to develop +because all the data structures and function parameters exchanged +between the API and the x86 code must be converted. + +User mode Linux [7] was the only solution before QEMU to launch a +Linux kernel as a process while not needing any host kernel +patches. However, user mode Linux requires heavy kernel patches while +QEMU accepts unpatched Linux kernels. The price to pay is that QEMU is +slower. + +The new Plex86 [8] PC virtualizer is done in the same spirit as the +qemu-fast system emulator. It requires a patched Linux kernel to work +(you cannot launch the same kernel on your PC), but the patches are +really small. As it is a PC virtualizer (no emulation is done except +for some priveledged instructions), it has the potential of being +faster than QEMU. The downside is that a complicated (and potentially +unsafe) host kernel patch is needed. + +The commercial PC Virtualizers (VMWare [9], VirtualPC [10], TwoOStwo +[11]) are faster than QEMU, but they all need specific, proprietary +and potentially unsafe host drivers. Moreover, they are unable to +provide cycle exact simulation as an emulator can. + +@section Portable dynamic translation + +QEMU is a dynamic translator. When it first encounters a piece of code, +it converts it to the host instruction set. Usually dynamic translators +are very complicated and highly CPU dependent. QEMU uses some tricks +which make it relatively easily portable and simple while achieving good +performances. + +The basic idea is to split every x86 instruction into fewer simpler +instructions. Each simple instruction is implemented by a piece of C +code (see @file{target-i386/op.c}). Then a compile time tool +(@file{dyngen}) takes the corresponding object file (@file{op.o}) +to generate a dynamic code generator which concatenates the simple +instructions to build a function (see @file{op.h:dyngen_code()}). + +In essence, the process is similar to [1], but more work is done at +compile time. + +A key idea to get optimal performances is that constant parameters can +be passed to the simple operations. For that purpose, dummy ELF +relocations are generated with gcc for each constant parameter. Then, +the tool (@file{dyngen}) can locate the relocations and generate the +appriopriate C code to resolve them when building the dynamic code. + +That way, QEMU is no more difficult to port than a dynamic linker. + +To go even faster, GCC static register variables are used to keep the +state of the virtual CPU. + +@section Register allocation + +Since QEMU uses fixed simple instructions, no efficient register +allocation can be done. However, because RISC CPUs have a lot of +register, most of the virtual CPU state can be put in registers without +doing complicated register allocation. + +@section Condition code optimisations + +Good CPU condition codes emulation (@code{EFLAGS} register on x86) is a +critical point to get good performances. QEMU uses lazy condition code +evaluation: instead of computing the condition codes after each x86 +instruction, it just stores one operand (called @code{CC_SRC}), the +result (called @code{CC_DST}) and the type of operation (called +@code{CC_OP}). + +@code{CC_OP} is almost never explicitely set in the generated code +because it is known at translation time. + +In order to increase performances, a backward pass is performed on the +generated simple instructions (see +@code{target-i386/translate.c:optimize_flags()}). When it can be proved that +the condition codes are not needed by the next instructions, no +condition codes are computed at all. + +@section CPU state optimisations + +The x86 CPU has many internal states which change the way it evaluates +instructions. In order to achieve a good speed, the translation phase +considers that some state information of the virtual x86 CPU cannot +change in it. For example, if the SS, DS and ES segments have a zero +base, then the translator does not even generate an addition for the +segment base. + +[The FPU stack pointer register is not handled that way yet]. + +@section Translation cache + +A 16 MByte cache holds the most recently used translations. For +simplicity, it is completely flushed when it is full. A translation unit +contains just a single basic block (a block of x86 instructions +terminated by a jump or by a virtual CPU state change which the +translator cannot deduce statically). + +@section Direct block chaining + +After each translated basic block is executed, QEMU uses the simulated +Program Counter (PC) and other cpu state informations (such as the CS +segment base value) to find the next basic block. + +In order to accelerate the most common cases where the new simulated PC +is known, QEMU can patch a basic block so that it jumps directly to the +next one. + +The most portable code uses an indirect jump. An indirect jump makes +it easier to make the jump target modification atomic. On some host +architectures (such as x86 or PowerPC), the @code{JUMP} opcode is +directly patched so that the block chaining has no overhead. + +@section Self-modifying code and translated code invalidation + +Self-modifying code is a special challenge in x86 emulation because no +instruction cache invalidation is signaled by the application when code +is modified. + +When translated code is generated for a basic block, the corresponding +host page is write protected if it is not already read-only (with the +system call @code{mprotect()}). Then, if a write access is done to the +page, Linux raises a SEGV signal. QEMU then invalidates all the +translated code in the page and enables write accesses to the page. + +Correct translated code invalidation is done efficiently by maintaining +a linked list of every translated block contained in a given page. Other +linked lists are also maintained to undo direct block chaining. + +Although the overhead of doing @code{mprotect()} calls is important, +most MSDOS programs can be emulated at reasonnable speed with QEMU and +DOSEMU. + +Note that QEMU also invalidates pages of translated code when it detects +that memory mappings are modified with @code{mmap()} or @code{munmap()}. + +When using a software MMU, the code invalidation is more efficient: if +a given code page is invalidated too often because of write accesses, +then a bitmap representing all the code inside the page is +built. Every store into that page checks the bitmap to see if the code +really needs to be invalidated. It avoids invalidating the code when +only data is modified in the page. + +@section Exception support + +longjmp() is used when an exception such as division by zero is +encountered. + +The host SIGSEGV and SIGBUS signal handlers are used to get invalid +memory accesses. The exact CPU state can be retrieved because all the +x86 registers are stored in fixed host registers. The simulated program +counter is found by retranslating the corresponding basic block and by +looking where the host program counter was at the exception point. + +The virtual CPU cannot retrieve the exact @code{EFLAGS} register because +in some cases it is not computed because of condition code +optimisations. It is not a big concern because the emulated code can +still be restarted in any cases. + +@section MMU emulation + +For system emulation, QEMU uses the mmap() system call to emulate the +target CPU MMU. It works as long the emulated OS does not use an area +reserved by the host OS (such as the area above 0xc0000000 on x86 +Linux). + +In order to be able to launch any OS, QEMU also supports a soft +MMU. In that mode, the MMU virtual to physical address translation is +done at every memory access. QEMU uses an address translation cache to +speed up the translation. + +In order to avoid flushing the translated code each time the MMU +mappings change, QEMU uses a physically indexed translation cache. It +means that each basic block is indexed with its physical address. + +When MMU mappings change, only the chaining of the basic blocks is +reset (i.e. a basic block can no longer jump directly to another one). + +@section Hardware interrupts + +In order to be faster, QEMU does not check at every basic block if an +hardware interrupt is pending. Instead, the user must asynchrously +call a specific function to tell that an interrupt is pending. This +function resets the chaining of the currently executing basic +block. It ensures that the execution will return soon in the main loop +of the CPU emulator. Then the main loop can test if the interrupt is +pending and handle it. + +@section User emulation specific details + +@subsection Linux system call translation + +QEMU includes a generic system call translator for Linux. It means that +the parameters of the system calls can be converted to fix the +endianness and 32/64 bit issues. The IOCTLs are converted with a generic +type description system (see @file{ioctls.h} and @file{thunk.c}). + +QEMU supports host CPUs which have pages bigger than 4KB. It records all +the mappings the process does and try to emulated the @code{mmap()} +system calls in cases where the host @code{mmap()} call would fail +because of bad page alignment. + +@subsection Linux signals + +Normal and real-time signals are queued along with their information +(@code{siginfo_t}) as it is done in the Linux kernel. Then an interrupt +request is done to the virtual CPU. When it is interrupted, one queued +signal is handled by generating a stack frame in the virtual CPU as the +Linux kernel does. The @code{sigreturn()} system call is emulated to return +from the virtual signal handler. + +Some signals (such as SIGALRM) directly come from the host. Other +signals are synthetized from the virtual CPU exceptions such as SIGFPE +when a division by zero is done (see @code{main.c:cpu_loop()}). + +The blocked signal mask is still handled by the host Linux kernel so +that most signal system calls can be redirected directly to the host +Linux kernel. Only the @code{sigaction()} and @code{sigreturn()} system +calls need to be fully emulated (see @file{signal.c}). + +@subsection clone() system call and threads + +The Linux clone() system call is usually used to create a thread. QEMU +uses the host clone() system call so that real host threads are created +for each emulated thread. One virtual CPU instance is created for each +thread. + +The virtual x86 CPU atomic operations are emulated with a global lock so +that their semantic is preserved. + +Note that currently there are still some locking issues in QEMU. In +particular, the translated cache flush is not protected yet against +reentrancy. + +@subsection Self-virtualization + +QEMU was conceived so that ultimately it can emulate itself. Although +it is not very useful, it is an important test to show the power of the +emulator. + +Achieving self-virtualization is not easy because there may be address +space conflicts. QEMU solves this problem by being an executable ELF +shared object as the ld-linux.so ELF interpreter. That way, it can be +relocated at load time. + +@section Bibliography + +@table @asis + +@item [1] +@url{http://citeseer.nj.nec.com/piumarta98optimizing.html}, Optimizing +direct threaded code by selective inlining (1998) by Ian Piumarta, Fabio +Riccardi. + +@item [2] +@url{http://developer.kde.org/~sewardj/}, Valgrind, an open-source +memory debugger for x86-GNU/Linux, by Julian Seward. + +@item [3] +@url{http://bochs.sourceforge.net/}, the Bochs IA-32 Emulator Project, +by Kevin Lawton et al. + +@item [4] +@url{http://www.cs.rose-hulman.edu/~donaldlf/em86/index.html}, the EM86 +x86 emulator on Alpha-Linux. + +@item [5] +@url{http://www.usenix.org/publications/library/proceedings/usenix-nt97/full_papers/chernoff/chernoff.pdf}, +DIGITAL FX!32: Running 32-Bit x86 Applications on Alpha NT, by Anton +Chernoff and Ray Hookway. + +@item [6] +@url{http://www.willows.com/}, Windows API library emulation from +Willows Software. + +@item [7] +@url{http://user-mode-linux.sourceforge.net/}, +The User-mode Linux Kernel. + +@item [8] +@url{http://www.plex86.org/}, +The new Plex86 project. + +@item [9] +@url{http://www.vmware.com/}, +The VMWare PC virtualizer. + +@item [10] +@url{http://www.microsoft.com/windowsxp/virtualpc/}, +The VirtualPC PC virtualizer. + +@item [11] +@url{http://www.twoostwo.org/}, +The TwoOStwo PC virtualizer. + +@end table + +@chapter Regression Tests + +In the directory @file{tests/}, various interesting testing programs +are available. There are used for regression testing. + +@section @file{test-i386} + +This program executes most of the 16 bit and 32 bit x86 instructions and +generates a text output. It can be compared with the output obtained with +a real CPU or another emulator. The target @code{make test} runs this +program and a @code{diff} on the generated output. + +The Linux system call @code{modify_ldt()} is used to create x86 selectors +to test some 16 bit addressing and 32 bit with segmentation cases. + +The Linux system call @code{vm86()} is used to test vm86 emulation. + +Various exceptions are raised to test most of the x86 user space +exception reporting. + +@section @file{linux-test} + +This program tests various Linux system calls. It is used to verify +that the system call parameters are correctly converted between target +and host CPUs. + +@section @file{qruncom.c} + +Example of usage of @code{libqemu} to emulate a user mode i386 CPU. diff --git a/tools/ioemu/qemu.1 b/tools/ioemu/qemu.1 new file mode 100644 index 0000000000..ddf0c2b651 --- /dev/null +++ b/tools/ioemu/qemu.1 @@ -0,0 +1,457 @@ +.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14 +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sh \" Subsection heading +.br +.if t .Sp +.ne 5 +.PP +\fB\\$1\fR +.PP +.. +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. | will give a +.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to +.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' +.\" expand to `' in nroff, nothing in troff, for use with C<>. +.tr \(*W-|\(bv\*(Tr +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` "" +. ds C' "" +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.if \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.\" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.hy 0 +.if n .na +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "QEMU 1" +.TH QEMU 1 "2005-05-19" " " " " +.SH "NAME" +qemu \- QEMU System Emulator +.SH "SYNOPSIS" +.IX Header "SYNOPSIS" +usage: qemu [options] [disk_image] +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +The \s-1QEMU\s0 System emulator simulates a complete \s-1PC\s0. +.PP +In order to meet specific user needs, two versions of \s-1QEMU\s0 are +available: +.IP "1." 4 +\&\f(CW\*(C`qemu\-fast\*(C'\fR uses the host Memory Management Unit (\s-1MMU\s0) to +simulate the x86 \s-1MMU\s0. It is \fIfast\fR but has limitations because +the whole 4 \s-1GB\s0 address space cannot be used and some memory mapped +peripherials cannot be emulated accurately yet. Therefore, a specific +guest Linux kernel can be used +.Sp +Moreover there is no separation between the host and target address +spaces, so it offers no security (the target \s-1OS\s0 can modify the +\&\f(CW\*(C`qemu\-fast\*(C'\fR code by writing at the right addresses). +.IP "2." 4 +\&\f(CW\*(C`qemu\*(C'\fR uses a software \s-1MMU\s0. It is about \fItwo times slower\fR +but gives a more accurate emulation and a complete separation between +the host and target address spaces. +.PP +\&\s-1QEMU\s0 emulates the following \s-1PC\s0 peripherials: +.IP "\-" 4 +i440FX host \s-1PCI\s0 bridge and \s-1PIIX3\s0 \s-1PCI\s0 to \s-1ISA\s0 bridge +.IP "\-" 4 +Cirrus \s-1CLGD\s0 5446 \s-1PCI\s0 \s-1VGA\s0 card or dummy \s-1VGA\s0 card with Bochs \s-1VESA\s0 +extensions (hardware level, including all non standard modes). +.IP "\-" 4 +\&\s-1PS/2\s0 mouse and keyboard +.IP "\-" 4 +2 \s-1PCI\s0 \s-1IDE\s0 interfaces with hard disk and CD-ROM support +.IP "\-" 4 +Floppy disk +.IP "\-" 4 +\&\s-1NE2000\s0 \s-1PCI\s0 network adapters +.IP "\-" 4 +Serial ports +.IP "\-" 4 +Soundblaster 16 card +.PP +\&\s-1QEMU\s0 uses the \s-1PC\s0 \s-1BIOS\s0 from the Bochs project and the Plex86/Bochs \s-1LGPL\s0 +\&\s-1VGA\s0 \s-1BIOS\s0. +.SH "OPTIONS" +.IX Header "OPTIONS" +\&\fIdisk_image\fR is a raw hard disk image for \s-1IDE\s0 hard disk 0. +.PP +General options: +.IP "\fB\-fda file\fR" 4 +.IX Item "-fda file" +.PD 0 +.IP "\fB\-fdb file\fR" 4 +.IX Item "-fdb file" +.PD +Use \fIfile\fR as floppy disk 0/1 image You can +use the host floppy by using \fI/dev/fd0\fR as filename. +.IP "\fB\-hda file\fR" 4 +.IX Item "-hda file" +.PD 0 +.IP "\fB\-hdb file\fR" 4 +.IX Item "-hdb file" +.IP "\fB\-hdc file\fR" 4 +.IX Item "-hdc file" +.IP "\fB\-hdd file\fR" 4 +.IX Item "-hdd file" +.PD +Use \fIfile\fR as hard disk 0, 1, 2 or 3 image +.IP "\fB\-cdrom file\fR" 4 +.IX Item "-cdrom file" +Use \fIfile\fR as CD-ROM image (you cannot use \fB\-hdc\fR and and +\&\fB\-cdrom\fR at the same time). You can use the host CD-ROM by +using \fI/dev/cdrom\fR as filename. +.IP "\fB\-boot [a|c|d]\fR" 4 +.IX Item "-boot [a|c|d]" +Boot on floppy (a), hard disk (c) or CD-ROM (d). Hard disk boot is +the default. +.IP "\fB\-snapshot\fR" 4 +.IX Item "-snapshot" +Write to temporary files instead of disk image files. In this case, +the raw disk image you use is not written back. You can however force +the write back by pressing \fBC\-a s\fR +.IP "\fB\-m megs\fR" 4 +.IX Item "-m megs" +Set virtual \s-1RAM\s0 size to \fImegs\fR megabytes. Default is 128 \s-1MB\s0. +.IP "\fB\-nographic\fR" 4 +.IX Item "-nographic" +Normally, \s-1QEMU\s0 uses \s-1SDL\s0 to display the \s-1VGA\s0 output. With this option, +you can totally disable graphical output so that \s-1QEMU\s0 is a simple +command line application. The emulated serial port is redirected on +the console. Therefore, you can still use \s-1QEMU\s0 to debug a Linux kernel +with a serial console. +.IP "\fB\-enable\-audio\fR" 4 +.IX Item "-enable-audio" +The \s-1SB16\s0 emulation is disabled by default as it may give problems with +Windows. You can enable it manually with this option. +.IP "\fB\-localtime\fR" 4 +.IX Item "-localtime" +Set the real time clock to local time (the default is to \s-1UTC\s0 +time). This option is needed to have correct date in MS-DOS or +Windows. +.IP "\fB\-full\-screen\fR" 4 +.IX Item "-full-screen" +Start in full screen. +.PP +Network options: +.IP "\fB\-n script\fR" 4 +.IX Item "-n script" +Set \s-1TUN/TAP\s0 network init script [default=/etc/qemu\-ifup]. This script +is launched to configure the host network interface (usually tun0) +corresponding to the virtual \s-1NE2000\s0 card. +.IP "\fB\-macaddr addr\fR" 4 +.IX Item "-macaddr addr" +Set the mac address of the first interface (the format is +aa:bb:cc:dd:ee:ff in hexa). The mac address is incremented for each +new network interface. +.IP "\fB\-tun\-fd fd\fR" 4 +.IX Item "-tun-fd fd" +Assumes \fIfd\fR talks to a tap/tun host network interface and use +it. Read <\fBhttp://bellard.org/qemu/tetrinet.html\fR> to have an +example of its use. +.IP "\fB\-user\-net\fR" 4 +.IX Item "-user-net" +Use the user mode network stack. This is the default if no tun/tap +network init script is found. +.IP "\fB\-tftp prefix\fR" 4 +.IX Item "-tftp prefix" +When using the user mode network stack, activate a built-in \s-1TFTP\s0 +server. All filenames beginning with \fIprefix\fR can be downloaded +from the host to the guest using a \s-1TFTP\s0 client. The \s-1TFTP\s0 client on the +guest must be configured in binary mode (use the command \f(CW\*(C`bin\*(C'\fR of +the Unix \s-1TFTP\s0 client). The host \s-1IP\s0 address on the guest is as usual +10.0.2.2. +.IP "\fB\-smb dir\fR" 4 +.IX Item "-smb dir" +When using the user mode network stack, activate a built-in \s-1SMB\s0 +server so that Windows OSes can access to the host files in \fIdir\fR +transparently. +.Sp +In the guest Windows \s-1OS\s0, the line: +.Sp +.Vb 1 +\& 10.0.2.4 smbserver +.Ve +.Sp +must be added in the file \fIC:\eWINDOWS\eLMHOSTS\fR (for windows 9x/Me) +or \fIC:\eWINNT\eSYSTEM32\eDRIVERS\eETC\eLMHOSTS\fR (Windows \s-1NT/2000\s0). +.Sp +Then \fIdir\fR can be accessed in \fI\e\esmbserver\eqemu\fR. +.Sp +Note that a \s-1SAMBA\s0 server must be installed on the host \s-1OS\s0 in +\&\fI/usr/sbin/smbd\fR. \s-1QEMU\s0 was tested succesfully with smbd version +2.2.7a from the Red Hat 9. +.IP "\fB\-redir [tcp|udp]:host\-port:[guest\-host]:guest\-port\fR" 4 +.IX Item "-redir [tcp|udp]:host-port:[guest-host]:guest-port" +When using the user mode network stack, redirect incoming \s-1TCP\s0 or \s-1UDP\s0 +connections to the host port \fIhost-port\fR to the guest +\&\fIguest-host\fR on guest port \fIguest-port\fR. If \fIguest-host\fR +is not specified, its value is 10.0.2.15 (default address given by the +built-in \s-1DHCP\s0 server). +.Sp +For example, to redirect host X11 connection from screen 1 to guest +screen 0, use the following: +.Sp +.Vb 4 +\& # on the host +\& qemu -redir tcp:6001::6000 [...] +\& # this host xterm should open in the guest X11 server +\& xterm -display :1 +.Ve +.Sp +To redirect telnet connections from host port 5555 to telnet port on +the guest, use the following: +.Sp +.Vb 3 +\& # on the host +\& qemu -redir tcp:5555::23 [...] +\& telnet localhost 5555 +.Ve +.Sp +Then when you use on the host \f(CW\*(C`telnet localhost 5555\*(C'\fR, you +connect to the guest telnet server. +.IP "\fB\-dummy\-net\fR" 4 +.IX Item "-dummy-net" +Use the dummy network stack: no packet will be received by the network +cards. +.PP +Linux boot specific. When using this options, you can use a given +Linux kernel without installing it in the disk image. It can be useful +for easier testing of various kernels. +.IP "\fB\-kernel bzImage\fR" 4 +.IX Item "-kernel bzImage" +Use \fIbzImage\fR as kernel image. +.IP "\fB\-append cmdline\fR" 4 +.IX Item "-append cmdline" +Use \fIcmdline\fR as kernel command line +.IP "\fB\-initrd file\fR" 4 +.IX Item "-initrd file" +Use \fIfile\fR as initial ram disk. +.PP +Debug/Expert options: +.IP "\fB\-serial dev\fR" 4 +.IX Item "-serial dev" +Redirect the virtual serial port to host device \fIdev\fR. Available +devices are: +.RS 4 +.ie n .IP """vc""" 4 +.el .IP "\f(CWvc\fR" 4 +.IX Item "vc" +Virtual console +.ie n .IP """pty""" 4 +.el .IP "\f(CWpty\fR" 4 +.IX Item "pty" +[Linux only] Pseudo \s-1TTY\s0 (a new \s-1PTY\s0 is automatically allocated) +.ie n .IP """null""" 4 +.el .IP "\f(CWnull\fR" 4 +.IX Item "null" +void device +.ie n .IP """stdio""" 4 +.el .IP "\f(CWstdio\fR" 4 +.IX Item "stdio" +[Unix only] standard input/output +.RE +.RS 4 +.Sp +The default device is \f(CW\*(C`vc\*(C'\fR in graphical mode and \f(CW\*(C`stdio\*(C'\fR in +non graphical mode. +.Sp +This option can be used several times to simulate up to 4 serials +ports. +.RE +.IP "\fB\-monitor dev\fR" 4 +.IX Item "-monitor dev" +Redirect the monitor to host device \fIdev\fR (same devices as the +serial port). +The default device is \f(CW\*(C`vc\*(C'\fR in graphical mode and \f(CW\*(C`stdio\*(C'\fR in +non graphical mode. +.IP "\fB\-s\fR" 4 +.IX Item "-s" +Wait gdb connection to port 1234 +.IP "\fB\-p port\fR" 4 +.IX Item "-p port" +Change gdb connection port. +.IP "\fB\-S\fR" 4 +.IX Item "-S" +Do not start \s-1CPU\s0 at startup (you must type 'c' in the monitor). +.IP "\fB\-d\fR" 4 +.IX Item "-d" +Output log in /tmp/qemu.log +.IP "\fB\-isa\fR" 4 +.IX Item "-isa" +Simulate an ISA-only system (default is \s-1PCI\s0 system). +.IP "\fB\-std\-vga\fR" 4 +.IX Item "-std-vga" +Simulate a standard \s-1VGA\s0 card with Bochs \s-1VBE\s0 extensions (default is +Cirrus Logic \s-1GD5446\s0 \s-1PCI\s0 \s-1VGA\s0) +.IP "\fB\-loadvm file\fR" 4 +.IX Item "-loadvm file" +Start right away with a saved state (\f(CW\*(C`loadvm\*(C'\fR in monitor) +.PP +During the graphical emulation, you can use the following keys: +.IP "\fBCtrl-Alt-f\fR" 4 +.IX Item "Ctrl-Alt-f" +Toggle full screen +.IP "\fBCtrl-Alt-n\fR" 4 +.IX Item "Ctrl-Alt-n" +Switch to virtual console 'n'. Standard console mappings are: +.RS 4 +.IP "\fI1\fR" 4 +.IX Item "1" +Target system display +.IP "\fI2\fR" 4 +.IX Item "2" +Monitor +.IP "\fI3\fR" 4 +.IX Item "3" +Serial port +.RE +.RS 4 +.RE +.IP "\fBCtrl-Alt\fR" 4 +.IX Item "Ctrl-Alt" +Toggle mouse and keyboard grab. +.PP +In the virtual consoles, you can use \fBCtrl-Up\fR, \fBCtrl-Down\fR, +\&\fBCtrl-PageUp\fR and \fBCtrl-PageDown\fR to move in the back log. +.PP +During emulation, if you are using the \fB\-nographic\fR option, use +\&\fBCtrl-a h\fR to get terminal commands: +.IP "\fBCtrl-a h\fR" 4 +.IX Item "Ctrl-a h" +Print this help +.IP "\fBCtrl-a x\fR" 4 +.IX Item "Ctrl-a x" +Exit emulatior +.IP "\fBCtrl-a s\fR" 4 +.IX Item "Ctrl-a s" +Save disk data back to file (if \-snapshot) +.IP "\fBCtrl-a b\fR" 4 +.IX Item "Ctrl-a b" +Send break (magic sysrq in Linux) +.IP "\fBCtrl-a c\fR" 4 +.IX Item "Ctrl-a c" +Switch between console and monitor +.IP "\fBCtrl-a Ctrl-a\fR" 4 +.IX Item "Ctrl-a Ctrl-a" +Send Ctrl-a +.PP +The following options are specific to the PowerPC emulation: +.IP "\fB\-prep\fR" 4 +.IX Item "-prep" +Simulate a \s-1PREP\s0 system (default is PowerMAC) +.IP "\fB\-g WxH[xDEPTH]\fR" 4 +.IX Item "-g WxH[xDEPTH]" +Set the initial \s-1VGA\s0 graphic mode. The default is 800x600x15. +.SH "SEE ALSO" +.IX Header "SEE ALSO" +The \s-1HTML\s0 documentation of \s-1QEMU\s0 for more precise information and Linux +user mode emulator invocation. +.SH "AUTHOR" +.IX Header "AUTHOR" +Fabrice Bellard diff --git a/tools/ioemu/readline.c b/tools/ioemu/readline.c new file mode 100644 index 0000000000..5ed0971177 --- /dev/null +++ b/tools/ioemu/readline.c @@ -0,0 +1,424 @@ +/* + * QEMU readline utility + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +#define TERM_CMD_BUF_SIZE 4095 +#define TERM_MAX_CMDS 64 +#define NB_COMPLETIONS_MAX 256 + +#define IS_NORM 0 +#define IS_ESC 1 +#define IS_CSI 2 + +#define printf do_not_use_printf + +static char term_cmd_buf[TERM_CMD_BUF_SIZE + 1]; +static int term_cmd_buf_index; +static int term_cmd_buf_size; + +static char term_last_cmd_buf[TERM_CMD_BUF_SIZE + 1]; +static int term_last_cmd_buf_index; +static int term_last_cmd_buf_size; + +static int term_esc_state; +static int term_esc_param; + +static char *term_history[TERM_MAX_CMDS]; +static int term_hist_entry = -1; + +static int nb_completions; +int completion_index; +static char *completions[NB_COMPLETIONS_MAX]; + +static ReadLineFunc *term_readline_func; +static int term_is_password; +static char term_prompt[256]; +static void *term_readline_opaque; + +static void term_show_prompt2(void) +{ + term_printf("%s", term_prompt); + term_flush(); + term_last_cmd_buf_index = 0; + term_last_cmd_buf_size = 0; + term_esc_state = IS_NORM; +} + +static void term_show_prompt(void) +{ + term_show_prompt2(); + term_cmd_buf_index = 0; + term_cmd_buf_size = 0; +} + +/* update the displayed command line */ +static void term_update(void) +{ + int i, delta, len; + + if (term_cmd_buf_size != term_last_cmd_buf_size || + memcmp(term_cmd_buf, term_last_cmd_buf, term_cmd_buf_size) != 0) { + for(i = 0; i < term_last_cmd_buf_index; i++) { + term_printf("\033[D"); + } + term_cmd_buf[term_cmd_buf_size] = '\0'; + if (term_is_password) { + len = strlen(term_cmd_buf); + for(i = 0; i < len; i++) + term_printf("*"); + } else { + term_printf("%s", term_cmd_buf); + } + term_printf("\033[K"); + memcpy(term_last_cmd_buf, term_cmd_buf, term_cmd_buf_size); + term_last_cmd_buf_size = term_cmd_buf_size; + term_last_cmd_buf_index = term_cmd_buf_size; + } + if (term_cmd_buf_index != term_last_cmd_buf_index) { + delta = term_cmd_buf_index - term_last_cmd_buf_index; + if (delta > 0) { + for(i = 0;i < delta; i++) { + term_printf("\033[C"); + } + } else { + delta = -delta; + for(i = 0;i < delta; i++) { + term_printf("\033[D"); + } + } + term_last_cmd_buf_index = term_cmd_buf_index; + } + term_flush(); +} + +static void term_insert_char(int ch) +{ + if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) { + memmove(term_cmd_buf + term_cmd_buf_index + 1, + term_cmd_buf + term_cmd_buf_index, + term_cmd_buf_size - term_cmd_buf_index); + term_cmd_buf[term_cmd_buf_index] = ch; + term_cmd_buf_size++; + term_cmd_buf_index++; + } +} + +static void term_backward_char(void) +{ + if (term_cmd_buf_index > 0) { + term_cmd_buf_index--; + } +} + +static void term_forward_char(void) +{ + if (term_cmd_buf_index < term_cmd_buf_size) { + term_cmd_buf_index++; + } +} + +static void term_delete_char(void) +{ + if (term_cmd_buf_index < term_cmd_buf_size) { + memmove(term_cmd_buf + term_cmd_buf_index, + term_cmd_buf + term_cmd_buf_index + 1, + term_cmd_buf_size - term_cmd_buf_index - 1); + term_cmd_buf_size--; + } +} + +static void term_backspace(void) +{ + if (term_cmd_buf_index > 0) { + term_backward_char(); + term_delete_char(); + } +} + +static void term_bol(void) +{ + term_cmd_buf_index = 0; +} + +static void term_eol(void) +{ + term_cmd_buf_index = term_cmd_buf_size; +} + +static void term_up_char(void) +{ + int idx; + + if (term_hist_entry == 0) + return; + if (term_hist_entry == -1) { + /* Find latest entry */ + for (idx = 0; idx < TERM_MAX_CMDS; idx++) { + if (term_history[idx] == NULL) + break; + } + term_hist_entry = idx; + } + term_hist_entry--; + if (term_hist_entry >= 0) { + pstrcpy(term_cmd_buf, sizeof(term_cmd_buf), + term_history[term_hist_entry]); + term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf); + } +} + +static void term_down_char(void) +{ + if (term_hist_entry == TERM_MAX_CMDS - 1 || term_hist_entry == -1) + return; + if (term_history[++term_hist_entry] != NULL) { + pstrcpy(term_cmd_buf, sizeof(term_cmd_buf), + term_history[term_hist_entry]); + } else { + term_hist_entry = -1; + } + term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf); +} + +static void term_hist_add(const char *cmdline) +{ + char *hist_entry, *new_entry; + int idx; + + if (cmdline[0] == '\0') + return; + new_entry = NULL; + if (term_hist_entry != -1) { + /* We were editing an existing history entry: replace it */ + hist_entry = term_history[term_hist_entry]; + idx = term_hist_entry; + if (strcmp(hist_entry, cmdline) == 0) { + goto same_entry; + } + } + /* Search cmdline in history buffers */ + for (idx = 0; idx < TERM_MAX_CMDS; idx++) { + hist_entry = term_history[idx]; + if (hist_entry == NULL) + break; + if (strcmp(hist_entry, cmdline) == 0) { + same_entry: + new_entry = hist_entry; + /* Put this entry at the end of history */ + memmove(&term_history[idx], &term_history[idx + 1], + &term_history[TERM_MAX_CMDS] - &term_history[idx + 1]); + term_history[TERM_MAX_CMDS - 1] = NULL; + for (; idx < TERM_MAX_CMDS; idx++) { + if (term_history[idx] == NULL) + break; + } + break; + } + } + if (idx == TERM_MAX_CMDS) { + /* Need to get one free slot */ + free(term_history[0]); + memcpy(term_history, &term_history[1], + &term_history[TERM_MAX_CMDS] - &term_history[1]); + term_history[TERM_MAX_CMDS - 1] = NULL; + idx = TERM_MAX_CMDS - 1; + } + if (new_entry == NULL) + new_entry = strdup(cmdline); + term_history[idx] = new_entry; + term_hist_entry = -1; +} + +/* completion support */ + +void add_completion(const char *str) +{ + if (nb_completions < NB_COMPLETIONS_MAX) { + completions[nb_completions++] = qemu_strdup(str); + } +} + +static void term_completion(void) +{ + int len, i, j, max_width, nb_cols; + char *cmdline; + + nb_completions = 0; + + cmdline = qemu_malloc(term_cmd_buf_index + 1); + if (!cmdline) + return; + memcpy(cmdline, term_cmd_buf, term_cmd_buf_index); + cmdline[term_cmd_buf_index] = '\0'; + qemu_free(cmdline); + + /* no completion found */ + if (nb_completions <= 0) + return; + if (nb_completions == 1) { + len = strlen(completions[0]); + for(i = completion_index; i < len; i++) { + term_insert_char(completions[0][i]); + } + /* extra space for next argument. XXX: make it more generic */ + if (len > 0 && completions[0][len - 1] != '/') + term_insert_char(' '); + } else { + term_printf("\n"); + max_width = 0; + for(i = 0; i < nb_completions; i++) { + len = strlen(completions[i]); + if (len > max_width) + max_width = len; + } + max_width += 2; + if (max_width < 10) + max_width = 10; + else if (max_width > 80) + max_width = 80; + nb_cols = 80 / max_width; + j = 0; + for(i = 0; i < nb_completions; i++) { + term_printf("%-*s", max_width, completions[i]); + if (++j == nb_cols || i == (nb_completions - 1)) { + term_printf("\n"); + j = 0; + } + } + term_show_prompt2(); + } +} + +/* return true if command handled */ +void readline_handle_byte(int ch) +{ + switch(term_esc_state) { + case IS_NORM: + switch(ch) { + case 1: + term_bol(); + break; + case 4: + term_delete_char(); + break; + case 5: + term_eol(); + break; + case 9: + term_completion(); + break; + case 10: + case 13: + term_cmd_buf[term_cmd_buf_size] = '\0'; + if (!term_is_password) + term_hist_add(term_cmd_buf); + term_printf("\n"); + /* NOTE: readline_start can be called here */ + term_readline_func(term_readline_opaque, term_cmd_buf); + break; + case 27: + term_esc_state = IS_ESC; + break; + case 127: + case 8: + term_backspace(); + break; + case 155: + term_esc_state = IS_CSI; + break; + default: + if (ch >= 32) { + term_insert_char(ch); + } + break; + } + break; + case IS_ESC: + if (ch == '[') { + term_esc_state = IS_CSI; + term_esc_param = 0; + } else { + term_esc_state = IS_NORM; + } + break; + case IS_CSI: + switch(ch) { + case 'A': + case 'F': + term_up_char(); + break; + case 'B': + case 'E': + term_down_char(); + break; + case 'D': + term_backward_char(); + break; + case 'C': + term_forward_char(); + break; + case '0' ... '9': + term_esc_param = term_esc_param * 10 + (ch - '0'); + goto the_end; + case '~': + switch(term_esc_param) { + case 1: + term_bol(); + break; + case 3: + term_delete_char(); + break; + case 4: + term_eol(); + break; + } + break; + default: + break; + } + term_esc_state = IS_NORM; + the_end: + break; + } + term_update(); +} + +void readline_start(const char *prompt, int is_password, + ReadLineFunc *readline_func, void *opaque) +{ + pstrcpy(term_prompt, sizeof(term_prompt), prompt); + term_readline_func = readline_func; + term_readline_opaque = opaque; + term_is_password = is_password; + term_show_prompt(); +} + +const char *readline_get_history(unsigned int index) +{ + if (index >= TERM_MAX_CMDS) + return NULL; + return term_history[index]; +} + + diff --git a/tools/ioemu/sdl.c b/tools/ioemu/sdl.c new file mode 100644 index 0000000000..91c0e23d56 --- /dev/null +++ b/tools/ioemu/sdl.c @@ -0,0 +1,605 @@ +/* + * QEMU SDL display driver + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +#include + +/* keyboard stuff */ +#include +#include "keysym_adapter_sdl.h" +#include "keyboard_rdesktop.c" + +#ifndef _WIN32 +#include +#endif + +#if defined(__APPLE__) +#define CONFIG_SDL_GENERIC_KBD +#endif + +static SDL_Surface *screen; +static int gui_grab; /* if true, all keyboard/mouse events are grabbed */ +static int last_vm_running; +static int gui_saved_grab; +static int gui_fullscreen; +static int gui_key_modifier_pressed; +static int gui_keysym; +static void* kbd_layout=0; +static int gui_fullscreen_initial_grab; +static int gui_grab_code = KMOD_LALT | KMOD_LCTRL; +static uint8_t modifiers_state[256]; + +SDL_PixelFormat* sdl_get_format() { + return screen->format; +} + +static void sdl_update(DisplayState *ds, int x, int y, int w, int h) +{ + SDL_UpdateRect(screen, x, y, w, h); +} + +static void sdl_resize(DisplayState *ds, int w, int h) +{ + int flags; + + // printf("resizing to %d %d\n", w, h); + + flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL; + flags |= SDL_RESIZABLE; + if (gui_fullscreen) + flags |= SDL_FULLSCREEN; + screen = SDL_SetVideoMode(w, h, 0, flags); + if (!screen) { + fprintf(stderr, "Could not open SDL display\n"); + exit(1); + } + ds->data = screen->pixels; + ds->linesize = screen->pitch; + ds->depth = screen->format->BitsPerPixel; + ds->width = w; + ds->height = h; +} + +#ifdef CONFIG_SDL_GENERIC_KBD + +/* XXX: use keymap tables defined in the VNC patch because the + following code suppose you have a US keyboard. */ + +static const uint8_t scancodes[SDLK_LAST] = { + [SDLK_ESCAPE] = 0x01, + [SDLK_1] = 0x02, + [SDLK_2] = 0x03, + [SDLK_3] = 0x04, + [SDLK_4] = 0x05, + [SDLK_5] = 0x06, + [SDLK_6] = 0x07, + [SDLK_7] = 0x08, + [SDLK_8] = 0x09, + [SDLK_9] = 0x0a, + [SDLK_0] = 0x0b, + [SDLK_MINUS] = 0x0c, + [SDLK_EQUALS] = 0x0d, + [SDLK_BACKSPACE] = 0x0e, + [SDLK_TAB] = 0x0f, + [SDLK_q] = 0x10, + [SDLK_w] = 0x11, + [SDLK_e] = 0x12, + [SDLK_r] = 0x13, + [SDLK_t] = 0x14, + [SDLK_y] = 0x15, + [SDLK_u] = 0x16, + [SDLK_i] = 0x17, + [SDLK_o] = 0x18, + [SDLK_p] = 0x19, + [SDLK_LEFTBRACKET] = 0x1a, + [SDLK_RIGHTBRACKET] = 0x1b, + [SDLK_RETURN] = 0x1c, + [SDLK_LCTRL] = 0x1d, + [SDLK_a] = 0x1e, + [SDLK_s] = 0x1f, + [SDLK_d] = 0x20, + [SDLK_f] = 0x21, + [SDLK_g] = 0x22, + [SDLK_h] = 0x23, + [SDLK_j] = 0x24, + [SDLK_k] = 0x25, + [SDLK_l] = 0x26, + [SDLK_SEMICOLON] = 0x27, + [SDLK_QUOTE] = 0x28, + [SDLK_BACKQUOTE] = 0x29, + [SDLK_LSHIFT] = 0x2a, + [SDLK_BACKSLASH] = 0x2b, + [SDLK_z] = 0x2c, + [SDLK_x] = 0x2d, + [SDLK_c] = 0x2e, + [SDLK_v] = 0x2f, + [SDLK_b] = 0x30, + [SDLK_n] = 0x31, + [SDLK_m] = 0x32, + [SDLK_COMMA] = 0x33, + [SDLK_PERIOD] = 0x34, + [SDLK_SLASH] = 0x35, + [SDLK_KP_MULTIPLY] = 0x37, + [SDLK_LALT] = 0x38, + [SDLK_SPACE] = 0x39, + [SDLK_CAPSLOCK] = 0x3a, + [SDLK_F1] = 0x3b, + [SDLK_F2] = 0x3c, + [SDLK_F3] = 0x3d, + [SDLK_F4] = 0x3e, + [SDLK_F5] = 0x3f, + [SDLK_F6] = 0x40, + [SDLK_F7] = 0x41, + [SDLK_F8] = 0x42, + [SDLK_F9] = 0x43, + [SDLK_F10] = 0x44, + [SDLK_NUMLOCK] = 0x45, + [SDLK_SCROLLOCK] = 0x46, + [SDLK_KP7] = 0x47, + [SDLK_KP8] = 0x48, + [SDLK_KP9] = 0x49, + [SDLK_KP_MINUS] = 0x4a, + [SDLK_KP4] = 0x4b, + [SDLK_KP5] = 0x4c, + [SDLK_KP6] = 0x4d, + [SDLK_KP_PLUS] = 0x4e, + [SDLK_KP1] = 0x4f, + [SDLK_KP2] = 0x50, + [SDLK_KP3] = 0x51, + [SDLK_KP0] = 0x52, + [SDLK_KP_PERIOD] = 0x53, + [SDLK_PRINT] = 0x54, + [SDLK_LMETA] = 0x56, + + [SDLK_KP_ENTER] = 0x9c, + [SDLK_KP_DIVIDE] = 0xb5, + + [SDLK_UP] = 0xc8, + [SDLK_DOWN] = 0xd0, + [SDLK_RIGHT] = 0xcd, + [SDLK_LEFT] = 0xcb, + [SDLK_INSERT] = 0xd2, + [SDLK_HOME] = 0xc7, + [SDLK_END] = 0xcf, + [SDLK_PAGEUP] = 0xc9, + [SDLK_PAGEDOWN] = 0xd1, + [SDLK_DELETE] = 0xd3, +}; + +static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev) +{ + return scancodes[ev->keysym.sym]; +} + +#elif defined(_WIN32) + +static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev) +{ + return ev->keysym.scancode; +} + +#else + +static const uint8_t x_keycode_to_pc_keycode[61] = { + 0xc7, /* 97 Home */ + 0xc8, /* 98 Up */ + 0xc9, /* 99 PgUp */ + 0xcb, /* 100 Left */ + 0x4c, /* 101 KP-5 */ + 0xcd, /* 102 Right */ + 0xcf, /* 103 End */ + 0xd0, /* 104 Down */ + 0xd1, /* 105 PgDn */ + 0xd2, /* 106 Ins */ + 0xd3, /* 107 Del */ + 0x9c, /* 108 Enter */ + 0x9d, /* 109 Ctrl-R */ + 0x0, /* 110 Pause */ + 0xb7, /* 111 Print */ + 0xb5, /* 112 Divide */ + 0xb8, /* 113 Alt-R */ + 0xc6, /* 114 Break */ + 0x0, /* 115 */ + 0x0, /* 116 */ + 0x0, /* 117 */ + 0x0, /* 118 */ + 0x0, /* 119 */ + 0x70, /* 120 Hiragana_Katakana */ + 0x0, /* 121 */ + 0x0, /* 122 */ + 0x73, /* 123 backslash */ + 0x0, /* 124 */ + 0x0, /* 125 */ + 0x0, /* 126 */ + 0x0, /* 127 */ + 0x0, /* 128 */ + 0x79, /* 129 Henkan */ + 0x0, /* 130 */ + 0x7b, /* 131 Muhenkan */ + 0x0, /* 132 */ + 0x7d, /* 133 Yen */ + 0x0, /* 134 */ + 0x0, /* 135 */ + 0x47, /* 136 KP_7 */ + 0x48, /* 137 KP_8 */ + 0x49, /* 138 KP_9 */ + 0x4b, /* 139 KP_4 */ + 0x4c, /* 140 KP_5 */ + 0x4d, /* 141 KP_6 */ + 0x4f, /* 142 KP_1 */ + 0x50, /* 143 KP_2 */ + 0x51, /* 144 KP_3 */ + 0x52, /* 145 KP_0 */ + 0x53, /* 146 KP_. */ + 0x47, /* 147 KP_HOME */ + 0x48, /* 148 KP_UP */ + 0x49, /* 149 KP_PgUp */ + 0x4b, /* 150 KP_Left */ + 0x4c, /* 151 KP_ */ + 0x4d, /* 152 KP_Right */ + 0x4f, /* 153 KP_End */ + 0x50, /* 154 KP_Down */ + 0x51, /* 155 KP_PgDn */ + 0x52, /* 156 KP_Ins */ + 0x53, /* 157 KP_Del */ +}; + +static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev) +{ + int keycode; + + keycode = ev->keysym.scancode; + + if (keycode < 9) { + keycode = 0; + } else if (keycode < 97) { + keycode -= 8; /* just an offset */ + } else if (keycode < 158) { + /* use conversion table */ + keycode = x_keycode_to_pc_keycode[keycode - 97]; + } else { + keycode = 0; + } + return keycode; +} + +#endif + +static void reset_keys(void) +{ + int i; + for(i = 0; i < 256; i++) { + if (modifiers_state[i]) { + if (i & 0x80) + kbd_put_keycode(0xe0); + kbd_put_keycode(i | 0x80); + modifiers_state[i] = 0; + } + } +} + +static void sdl_process_key(SDL_KeyboardEvent *ev) +{ + int keycode, v; + + if(kbd_layout) + keycode=keysym2scancode(kbd_layout, ev->keysym.sym); + else { + + if (ev->keysym.sym == SDLK_PAUSE) { + /* specific case */ + v = 0; + if (ev->type == SDL_KEYUP) + v |= 0x80; + kbd_put_keycode(0xe1); + kbd_put_keycode(0x1d | v); + kbd_put_keycode(0x45 | v); + return; + } + + /* XXX: not portable, but avoids complicated mappings */ + keycode = sdl_keyevent_to_keycode(ev); + + switch(keycode) { + case 0x00: + /* sent when leaving window: reset the modifiers state */ + reset_keys(); + return; + case 0x2a: /* Left Shift */ + case 0x36: /* Right Shift */ + case 0x1d: /* Left CTRL */ + case 0x9d: /* Right CTRL */ + case 0x38: /* Left ALT */ + case 0xb8: /* Right ALT */ + if (ev->type == SDL_KEYUP) + modifiers_state[keycode] = 0; + else + modifiers_state[keycode] = 1; + break; + case 0x45: /* num lock */ + case 0x3a: /* caps lock */ + /* SDL does not send the key up event, so we generate it */ + kbd_put_keycode(keycode); + kbd_put_keycode(keycode | 0x80); + return; + } + } + + /* now send the key code */ + if (keycode & 0x80) + kbd_put_keycode(0xe0); + if (ev->type == SDL_KEYUP) + kbd_put_keycode(keycode | 0x80); + else + kbd_put_keycode(keycode & 0x7f); +} + +static void sdl_update_caption(void) +{ + char buf[1024]; + strcpy(buf, "VTXen"); + if (!vm_running) { + strcat(buf, " [Stopped]"); + } + if (gui_grab) { + strcat(buf, " - Press Ctrl-Alt to exit grab"); + } + SDL_WM_SetCaption(buf, "VTXen"); +} + +static void sdl_grab_start(void) +{ + SDL_ShowCursor(0); + SDL_WM_GrabInput(SDL_GRAB_ON); + /* dummy read to avoid moving the mouse */ + SDL_GetRelativeMouseState(NULL, NULL); + gui_grab = 1; + sdl_update_caption(); +} + +static void sdl_grab_end(void) +{ + SDL_WM_GrabInput(SDL_GRAB_OFF); + SDL_ShowCursor(1); + gui_grab = 0; + sdl_update_caption(); +} + +static void sdl_send_mouse_event(void) +{ + int dx, dy, dz, state, buttons; + state = SDL_GetRelativeMouseState(&dx, &dy); + buttons = 0; + if (state & SDL_BUTTON(SDL_BUTTON_LEFT)) + buttons |= MOUSE_EVENT_LBUTTON; + if (state & SDL_BUTTON(SDL_BUTTON_RIGHT)) + buttons |= MOUSE_EVENT_RBUTTON; + if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) + buttons |= MOUSE_EVENT_MBUTTON; + /* XXX: test wheel */ + dz = 0; +#ifdef SDL_BUTTON_WHEELUP + if (state & SDL_BUTTON(SDL_BUTTON_WHEELUP)) + dz--; + if (state & SDL_BUTTON(SDL_BUTTON_WHEELDOWN)) + dz++; +#endif + kbd_mouse_event(dx, dy, dz, buttons); +} + +static void toggle_full_screen(DisplayState *ds) +{ + gui_fullscreen = !gui_fullscreen; + sdl_resize(ds, screen->w, screen->h); + if (gui_fullscreen) { + gui_saved_grab = gui_grab; + sdl_grab_start(); + } else { + if (!gui_saved_grab) + sdl_grab_end(); + } + vga_invalidate_display(); + vga_update_display(); +} + +static void sdl_refresh(DisplayState *ds) +{ + SDL_Event ev1, *ev = &ev1; + int mod_state; + + if (last_vm_running != vm_running) { + last_vm_running = vm_running; + sdl_update_caption(); + } + + if (is_active_console(vga_console)) + vga_update_display(); + + while (SDL_PollEvent(ev)) { + switch (ev->type) { + case SDL_VIDEOEXPOSE: + sdl_update(ds, 0, 0, screen->w, screen->h); + break; + case SDL_KEYDOWN: + case SDL_KEYUP: + if (ev->type == SDL_KEYDOWN) { + mod_state = (SDL_GetModState() & gui_grab_code) == + gui_grab_code; + gui_key_modifier_pressed = mod_state; + if (gui_key_modifier_pressed) { + int keycode; + keycode = sdl_keyevent_to_keycode(&ev->key); + switch(keycode) { + case 0x21: /* 'f' key on US keyboard */ + toggle_full_screen(ds); + gui_keysym = 1; + break; + case 0x02 ... 0x0a: /* '1' to '9' keys */ + console_select(keycode - 0x02); + if (is_active_console(vga_console)) { + /* tell the vga console to redisplay itself */ + vga_invalidate_display(); + } else { + /* display grab if going to a text console */ + if (gui_grab) + sdl_grab_end(); + } + gui_keysym = 1; + break; + default: + break; + } + } else if (!is_active_console(vga_console)) { + int keysym; + keysym = 0; + if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) { + switch(ev->key.keysym.sym) { + case SDLK_UP: keysym = QEMU_KEY_CTRL_UP; break; + case SDLK_DOWN: keysym = QEMU_KEY_CTRL_DOWN; break; + case SDLK_LEFT: keysym = QEMU_KEY_CTRL_LEFT; break; + case SDLK_RIGHT: keysym = QEMU_KEY_CTRL_RIGHT; break; + case SDLK_HOME: keysym = QEMU_KEY_CTRL_HOME; break; + case SDLK_END: keysym = QEMU_KEY_CTRL_END; break; + case SDLK_PAGEUP: keysym = QEMU_KEY_CTRL_PAGEUP; break; + case SDLK_PAGEDOWN: keysym = QEMU_KEY_CTRL_PAGEDOWN; break; + default: break; + } + } else { + switch(ev->key.keysym.sym) { + case SDLK_UP: keysym = QEMU_KEY_UP; break; + case SDLK_DOWN: keysym = QEMU_KEY_DOWN; break; + case SDLK_LEFT: keysym = QEMU_KEY_LEFT; break; + case SDLK_RIGHT: keysym = QEMU_KEY_RIGHT; break; + case SDLK_HOME: keysym = QEMU_KEY_HOME; break; + case SDLK_END: keysym = QEMU_KEY_END; break; + case SDLK_PAGEUP: keysym = QEMU_KEY_PAGEUP; break; + case SDLK_PAGEDOWN: keysym = QEMU_KEY_PAGEDOWN; break; + case SDLK_BACKSPACE: keysym = QEMU_KEY_BACKSPACE; break; case SDLK_DELETE: keysym = QEMU_KEY_DELETE; break; + default: break; + } + } + if (keysym) { + kbd_put_keysym(keysym); + } else if (ev->key.keysym.unicode != 0) { + kbd_put_keysym(ev->key.keysym.unicode); + } + } + } else if (ev->type == SDL_KEYUP) { + mod_state = (ev->key.keysym.mod & gui_grab_code); + if (!mod_state) { + if (gui_key_modifier_pressed) { + gui_key_modifier_pressed = 0; + if (gui_keysym == 0) { + /* exit/enter grab if pressing Ctrl-Alt */ + if (!gui_grab) + sdl_grab_start(); + else + sdl_grab_end(); + /* SDL does not send back all the + modifiers key, so we must correct it */ + reset_keys(); + break; + } + gui_keysym = 0; + } + } + } + if (is_active_console(vga_console)) + sdl_process_key(&ev->key); + break; + case SDL_QUIT: + qemu_system_shutdown_request(); + break; + case SDL_MOUSEMOTION: + if (gui_grab) { + sdl_send_mouse_event(); + } + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + { + SDL_MouseButtonEvent *bev = &ev->button; + if (!gui_grab) { + if (ev->type == SDL_MOUSEBUTTONDOWN && + (bev->state & SDL_BUTTON_LMASK)) { + /* start grabbing all events */ + sdl_grab_start(); + } + } else { + sdl_send_mouse_event(); + } + } + break; + case SDL_ACTIVEEVENT: + if (gui_grab && (ev->active.gain & SDL_ACTIVEEVENTMASK) == 0 && + !gui_fullscreen_initial_grab) { + sdl_grab_end(); + } + break; + default: + break; + } + } +} + +static void sdl_cleanup(void) +{ + SDL_Quit(); +} + +void sdl_display_init(DisplayState *ds, int full_screen) +{ + int flags; + + if(keyboard_layout) + kbd_layout=init_keyboard_layout(keyboard_layout); + + flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE; + if (SDL_Init (flags)) { + fprintf(stderr, "Could not initialize SDL - exiting\n"); + exit(1); + } +#ifndef _WIN32 + /* NOTE: we still want Ctrl-C to work, so we undo the SDL redirections */ + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); +#endif + + ds->dpy_update = sdl_update; + ds->dpy_resize = sdl_resize; + ds->dpy_refresh = sdl_refresh; + + sdl_resize(ds, 640, 400); + sdl_update_caption(); + SDL_EnableKeyRepeat(250, 50); + SDL_EnableUNICODE(1); + gui_grab = 0; + + atexit(sdl_cleanup); + if (full_screen) { + gui_fullscreen = 1; + gui_fullscreen_initial_grab = 1; + sdl_grab_start(); + } +} diff --git a/tools/ioemu/target-i386-dm/device-model b/tools/ioemu/target-i386-dm/device-model new file mode 100755 index 0000000000..b25c175bbc --- /dev/null +++ b/tools/ioemu/target-i386-dm/device-model @@ -0,0 +1,69 @@ +#!/bin/sh + +. /etc/rc.d/init.d/functions + +qemubin=/usr/bin/qemu-dm + +ulimit -c unlimited + +# Use this for debugging: +#gdb --args /usr/sbin/qemu-dm -hda /var/images/qemu-linux.img -nographic \ +# -serial pty -l 'ioport,int' $* + +while getopts ":f:" opt; +do + case $opt in + f) QEMUCONFIGFILE=$OPTARG;shift;shift;; + \?) echo;; + esac +done + +echo $QEMUCONFIGFILE +if [ ! -z $QEMUCONFIGFILE ];then + . $QEMUCONFIGFILE +else + echo "no config file specified!" > /dev/tty + echo "no config file specified!" >> /tmp/qemustart.log + exit +fi + +PARMETER="" + +if [ ! -z $hda ];then +PARMETER="$PARMETER -hda $hda" +fi + +if [ ! -z $hdb ];then +PARMETER="$PARMETER -hdb $hdb" +fi + +if [ ! -z $hdc ];then +PARMETER="$PARMETER -hdc $hdc" +fi + +if [ ! -z $hdd ];then +PARMETER="$PARMETER -hdd $hdd" +fi + +if [ ! -z $nographic ] && [ $nographic -eq 1 ];then +PARMETER="$PARMETER -nographic" +fi + +vnc=${vnc:=1} +sdl=${sdl:=0} +if qemu-dm 2>&1 |grep vnc > /dev/null;then + if [ $vnc -eq 1 ] && [ $sdl -eq 1 ];then + PARMETER="$PARMETER -vnc-and-sdl -k en-us" + elif [ $vnc -eq 1 ];then + PARMETER="$PARMETER -vnc -k en-us" + fi +fi + +#optional cmdline for qemu +# -nographic \ +# -serial pty \ + + +PARMETER="$PARMETER -l int $*"; +echo "$qemubin $PARMETER" >>/tmp/qemustart.log +$qemubin $PARMETER & diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c new file mode 100644 index 0000000000..3704b08361 --- /dev/null +++ b/tools/ioemu/target-i386-dm/helper2.c @@ -0,0 +1,434 @@ +/* + * i386 helpers (without register variable usage) + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Main cpu loop for handling I/O requests coming from a virtual machine + * Copyright © 2004, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU Lesser General Public License, + * version 2.1, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "xc.h" +#include + +#include "cpu.h" +#include "exec-all.h" + +//#define DEBUG_MMU + +#ifdef USE_CODE_COPY +#include +#include +#include + +#include +/* According to POSIX 1003.1-2001 */ +#include + +/* According to earlier standards */ +#include +#include +#include +#include +#include +#include + +_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66) +#define modify_ldt_ldt_s user_desc +#endif +#endif /* USE_CODE_COPY */ + +void *shared_page; + +CPUX86State *cpu_86_init(void) +{ + CPUX86State *env; + static int inited; + + cpu_exec_init(); + + env = malloc(sizeof(CPUX86State)); + if (!env) + return NULL; + memset(env, 0, sizeof(CPUX86State)); + /* init various static tables */ + if (!inited) { + inited = 1; + } + cpu_single_env = env; + cpu_reset(env); + return env; +} + +/* NOTE: must be called outside the CPU execute loop */ +void cpu_reset(CPUX86State *env) +{ +} + +void cpu_x86_close(CPUX86State *env) +{ + free(env); +} + + +void cpu_dump_state(CPUState *env, FILE *f, + int (*cpu_fprintf)(FILE *f, const char *fmt, ...), + int flags) +{ +} + +/***********************************************************/ +/* x86 mmu */ +/* XXX: add PGE support */ + +void cpu_x86_set_a20(CPUX86State *env, int a20_state) +{ + a20_state = (a20_state != 0); + if (a20_state != ((env->a20_mask >> 20) & 1)) { +#if defined(DEBUG_MMU) + printf("A20 update: a20=%d\n", a20_state); +#endif + env->a20_mask = 0xffefffff | (a20_state << 20); + } +} + +target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) +{ + return addr; +} + +//the evtchn fd for polling +int evtchn_fd = -1; +//the evtchn port for polling the notification, should be inputed as bochs's parameter +u16 ioreq_port = 0; + +void *shared_page = NULL; + +//some functions to handle the io req packet + +//get the ioreq packets from share mem +ioreq_t* __cpu_get_ioreq(void) +{ + ioreq_t *req; + req = &((vcpu_iodata_t *) shared_page)->vp_ioreq; + if (req->state == STATE_IOREQ_READY) { + req->state = STATE_IOREQ_INPROCESS; + } else { + fprintf(logfile, "False I/O requrest ... in-service already: %x, pvalid: %x,port: %llx, data: %llx, count: %llx, size: %llx\n", req->state, req->pdata_valid, req->addr, req->u.data, req->count, req->size); + req = NULL; + } + + return req; +} + +//use poll to get the port notification +//ioreq_vec--out,the +//retval--the number of ioreq packet +ioreq_t* cpu_get_ioreq(void) +{ + int rc; + u16 buf[2]; + rc = read(evtchn_fd, buf, 2); + if (rc == 2 && buf[0] == ioreq_port){//got only one matched 16bit port index + // unmask the wanted port again + write(evtchn_fd, &ioreq_port, 2); + + //get the io packet from shared memory + return __cpu_get_ioreq(); + } + + //read error or read nothing + return NULL; +} + +unsigned long +do_inp(CPUState *env, unsigned long addr, unsigned long size) +{ + switch(size) { + case 1: + return cpu_inb(env, addr); + case 2: + return cpu_inw(env, addr); + case 4: + return cpu_inl(env, addr); + default: + fprintf(logfile, "inp: bad size: %lx %lx\n", addr, size); + exit(-1); + } +} + +void +do_outp(CPUState *env, unsigned long addr, unsigned long size, + unsigned long val) +{ + switch(size) { + case 1: + return cpu_outb(env, addr, val); + case 2: + return cpu_outw(env, addr, val); + case 4: + return cpu_outl(env, addr, val); + default: + fprintf(logfile, "outp: bad size: %lx %lx\n", addr, size); + exit(-1); + } +} + +extern void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, + int len, int is_write); + +static inline void +read_physical(target_phys_addr_t addr, unsigned long size, void *val) +{ + return cpu_physical_memory_rw(addr, val, size, 0); +} + +static inline void +write_physical(target_phys_addr_t addr, unsigned long size, void *val) +{ + return cpu_physical_memory_rw(addr, val, size, 1); +} + +//send the ioreq to device model +void cpu_dispatch_ioreq(CPUState *env, ioreq_t *req) +{ + int i; + int sign; + + sign = (req->df) ? -1 : 1; + + if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) { + if (req->size != 4) { + // Bochs expects higher bits to be 0 + req->u.data &= (1UL << (8 * req->size))-1; + } + } + + if (req->port_mm == 0){//port io + if(req->dir == IOREQ_READ){//read + if (!req->pdata_valid) { + req->u.data = do_inp(env, req->addr, req->size); + } else { + unsigned long tmp; + + for (i = 0; i < req->count; i++) { + tmp = do_inp(env, req->addr, req->size); + write_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), + req->size, &tmp); + } + } + } else if(req->dir == IOREQ_WRITE) { + if (!req->pdata_valid) { + do_outp(env, req->addr, req->size, req->u.data); + } else { + for (i = 0; i < req->count; i++) { + unsigned long tmp; + + read_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), req->size, + &tmp); + do_outp(env, req->addr, req->size, tmp); + } + } + + } + } else if (req->port_mm == 1){//memory map io + if (!req->pdata_valid) { + //handle stos + if(req->dir == IOREQ_READ) { //read + for (i = 0; i < req->count; i++) { + read_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &req->u.data); + } + } else if(req->dir == IOREQ_WRITE) { //write + for (i = 0; i < req->count; i++) { + write_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &req->u.data); + } + } + } else { + //handle movs + unsigned long tmp; + if (req->dir == IOREQ_READ) { + for (i = 0; i < req->count; i++) { + read_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &tmp); + write_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), req->size, &tmp); + } + } else if (req->dir == IOREQ_WRITE) { + for (i = 0; i < req->count; i++) { + read_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), req->size, &tmp); + write_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &tmp); + } + } + } + } + /* No state change if state = STATE_IORESP_HOOK */ + if (req->state == STATE_IOREQ_INPROCESS) + req->state = STATE_IORESP_READY; + env->send_event = 1; +} + +void +cpu_handle_ioreq(CPUState *env) +{ + ioreq_t *req = cpu_get_ioreq(); + if (req) + cpu_dispatch_ioreq(env, req); +} + +void +cpu_timer_handler(CPUState *env) +{ + cpu_handle_ioreq(env); +} + +int xc_handle; + +#include + +void +do_interrupt(CPUState *env, int vector) +{ + unsigned long *intr; + + // Send a message on the event channel. Add the vector to the shared mem + // page. + + intr = &(((vcpu_iodata_t *) shared_page)->vp_intr[0]); + set_bit(vector, intr); + fprintf(logfile, "injecting vector: %x\n", vector); + env->send_event = 1; +} + +//static unsigned long tsc_per_tick = 1; /* XXX: calibrate */ + +int main_loop(void) +{ + int vector; + fd_set rfds; + struct timeval tv; + extern CPUState *global_env; + extern int vm_running; + extern int shutdown_requested; + CPUState *env = global_env; + int retval; + extern void main_loop_wait(int); + + /* Watch stdin (fd 0) to see when it has input. */ + FD_ZERO(&rfds); + + while (1) { + if (vm_running) { + if (shutdown_requested) { + break; + } + } + + /* Wait up to one seconds. */ + tv.tv_sec = 0; + tv.tv_usec = 100000; + FD_SET(evtchn_fd, &rfds); + + env->send_event = 0; + retval = select(evtchn_fd+1, &rfds, NULL, NULL, &tv); + if (retval == -1) { + perror("select"); + return 0; + } + +#if __WORDSIZE == 32 +#define ULONGLONG_MAX 0xffffffffffffffffULL +#else +#define ULONGLONG_MAX ULONG_MAX +#endif + + main_loop_wait(0); + + cpu_timer_handler(env); + if (env->interrupt_request & CPU_INTERRUPT_HARD) { + env->interrupt_request &= ~CPU_INTERRUPT_HARD; + vector = cpu_get_pic_interrupt(env); + do_interrupt(env, vector); + } + + if (env->send_event) { + int ret; + ret = xc_evtchn_send(xc_handle, ioreq_port); + if (ret == -1) { + fprintf(logfile, "evtchn_send failed on port: %d\n", ioreq_port); + } + } + } + return 0; +} + +CPUState * +cpu_init() +{ + CPUX86State *env; + + cpu_exec_init(); + + env = malloc(sizeof(CPUX86State)); + if (!env) + return NULL; + memset(env, 0, sizeof(CPUX86State)); + + cpu_single_env = env; + + if (evtchn_fd != -1)//the evtchn has been opened by another cpu object + return NULL; + + //use nonblock reading not polling, may change in future. + evtchn_fd = open("/dev/xen/evtchn", O_RDWR|O_NONBLOCK); + if (evtchn_fd == -1) { + perror("open"); + return NULL; + } + + fprintf(logfile, "listening to port: %d\n", ioreq_port); + /*unmask the wanted port -- bind*/ + if (ioctl(evtchn_fd, ('E'<<8)|2, ioreq_port) == -1) { + perror("ioctl"); + return NULL; + } + + return env; +} diff --git a/tools/ioemu/target-i386-dm/qemu-ifup b/tools/ioemu/target-i386-dm/qemu-ifup new file mode 100755 index 0000000000..87bff3410c --- /dev/null +++ b/tools/ioemu/target-i386-dm/qemu-ifup @@ -0,0 +1,10 @@ +#!/bin/sh + +#. /etc/rc.d/init.d/functions +#ulimit -c unlimited + +echo 'config qemu network with xen bridge for ' +echo $* + +ifconfig $1 0.0.0.0 up +brctl addif xen-br0 $1 diff --git a/tools/ioemu/target-i386-dm/qemu-vgaram-bin.gz b/tools/ioemu/target-i386-dm/qemu-vgaram-bin.gz new file mode 100644 index 0000000000000000000000000000000000000000..86e44ab486a3452bb004b8b1dc5a655e77486024 GIT binary patch literal 3338 zcmeH_?ORd@1IB&UR@>TYd)jK#lxsP&(&1%Rt_-QPOqV%(Ghb<%nj$e@0FmIVxvf{D zG$l1*v+^}%sfZeI=31eWQZpn$IW%M-t3-7-B zfr7HjZBcGIh4vLa^Siw7C|{*!opdvf50aDApUdaNmYVI zWlw(lFnUEWmE7N!eqo>gcU#X#m8_teeLvZy9)At2YY04x-&b+}az|l#PE_FA{|@+Z z%>}IteH5Ypo&JjBJM)q@`Z6Qi*2Y&P zmFDc_UzT{=OD1=-luc44NezPm-Kme2GXL%k%z+f>p^g~9d_G5Gp7NH`7lh{c;7O~8 z*=2fJc~8(c6KpeIml?i&|2)UW?l){vja@xePQc-@ubQh>A6tVml_Gvhr&>FG8-odr z?a6N%A23+(a&9w|veS!reMsws#M=l|E9?FgNo30J<5q;Z@~a4E8&C^C;05Io%TI>h%TR;g9^zP$c0u}ocI zWP8{c9-W>nK%8R*Q!O;z?rO%v&e5eZ{9>6Rt<<|z5Xrxi6M6E}(f4zxDF&v*sMqd@ z2L|&9-yuVX6+NQ%t%@b_60eb*qFicG!t`7`)7bG)z$>ce*)3+V$~VSEl*E}4Q+21bHL=QAa75GcM07E*VsgGN zyuR5i@wHgzyKf5-`ynmAZp>!B`A=?mXa{}DUN(89BK&Gg+C|U))a(cD1ePp~OVfqf zTnWcKJJQ8{&t?K5N4`{)ep6bKgZh=KeW+3V4ttFD5Cr0xSTDK#Wkb#kbuWpv(~BB) z#K*&Y>hP4Xe?nni2)AvO=QLG{?Gf!SKkqM{Y?}P>FUZ&Kj4Ia}aE&xor|I6;pInpMWUc@AUjV4rkn#)F@7-F@*#u>SE$O=D_5(jYC?p zlr%nVTyUeF-1ktJS{pdAz3>ynr?in3TVnB5f_oj=w(5eZ+hmkRkDxdy3f9#!e zYQe~8dLq7N+J>DbaQ>X$!Al>WJ~qk+Ky)f$8pl#?L$@78n2;?@0}0bTLcFyL2U+ZA zkuQTY_0|k0Ra3J+b9gi?8f>Dx>Rtk9JA!NAUs{$U%ksBiH6IIMo;Rd^AQJUk>zzG1 zoddd@71Q=*mWC8FEnM{om2j=>x%yHHD>TjiwH20LnRs+uPmb4_ib!2)katrOjvTgpQq z`uPxaq%Z`|=WtfPP%cvT5*kQGhWPJ=i60uwY%I8G)+*|=UE>kcXoNB!$J02TJ=QM{ zJ}o|gEyyiLkJ;}YQSwb204vf&QkVJE$mhjS^sK z9QFh@cGG+VmQvWHP<(acp(W~w?U(jz%@x*<57Tw1^r7UdCnt*SjD?t$gk_rjceEgh zF{DIh>z;?MYdU2#SuAeqzvq|>rneOEJP!vL?3?a$!P)q6ZqMS!?QnQGNY-C3ONxpn z35R!Ai%V1Gq=^A|tVM#-v=+KhSo5wwI5wo|l=c~wN)z{+<4*M*ik5jMK@EZXinW>w zA80N3fj>!W`{(SFr|5ulpE*srJyvfzig3~tjapr1V~UgNK~=8?#71m@{?RB_l86GM zjz{o|EzFyLn|aQAeZ~M1r-cko5z3}-1JG1x!Ec-(h-uuZ@mojJPe660?6ddbq}3#o{_GkfoW~&eoE`rb299;cRxLQ7EXwX#@#f$ z9RUHG$MraxQNH4iOP`y09NF(ToO4FknGH>B#3y#jM4&JiIh^lnm2cH|h2T~^Im*E; z&B;8c!w6N2#X;cWZ<|qV1rc2Pk<_JIay-o|2SDb1+mMV@1RZ>75)xblmZ z^Limf*^u@;!6}GU2m~w6zFO*Q1s&XTpY09;FM~OM22AgNSRlqtcTS@c#5CYtpsB^FTn7Xz8 zIYRx5850wKL@VjDk?_=bT#9e3-igR!1t8Rsyo7s_RTZliSjb9F=(bd1L33eJI~HIH zXl1)9h52mVeLGizl6l~@#mb#3JT$}k?VbZ(pm$w!$bYnVu3|6SbnE00IB7^B^GKZ_ zzJiF;szR|V-1(k$;B8E!XKA%c!ii!0-B+w^9!aNt0q=ZiaTNkSDktGVdcW|1g_ZAV zf%XqReO3I&#+X~Z`MSGVg|7MdZ%1!9peh5PaX<-rvNL-IAeRf%skhM28f**gNhp2@ zc=ZX_*As}bIEs0MmtGAGRp#*NXDNjym@qJrjh-@P3NCkf+g$aZXzx)Fk!+!0PSYA4!f#n zJjM(LFgpbsP^h+za5BaST^}oE;gA#iMj0G1jJ92OPjwB%@sgDy*oEFyxZy zBT!uialMj2i^U%6V-nC-HL%Kx6*k3T6Ap0IT8WnmBX<|QV)Xp!penNbz-B$RMMcIa z^Le1L5K%W^xeC$^RNjKQTZtz@waU!uIf-p{V3E)b#RS(KG2KK+t7gC{l##Tb@kXW& zFn6N0RSqWO0M!ZL21>extj)8NuLAH7TTj@DTaT@o>1w8fl~v?6ar*-GpW1=3sA6>w zRl5navHX5_xk44jz;mrE#7i1@4xh*a0)!+(-MYBKK zbF*7RCiMVCxyna-I-OYMVAs^SVAIq=mq`FysBU|N#pCSlmoCEj6j-u{d+q_ERj$8J zUBYDQrd-Z&o(cZ70{)H8bk#RXF(q%NNFi~b58Pq@dV|b#K_~Y*o?Kw}tW`Xk=sS~O zhH|7YWW;PNKSV_w>1#g;^*W_M-RuyO test-i386.ref +else +test: +endif + $(QEMU) test-i386 > test-i386.out + @if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi +ifeq ($(ARCH),i386) + $(QEMU) -no-code-copy test-i386 > test-i386.out + @if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK (no code copy)"; fi +endif + +# generic Linux and CPU test +linux-test: linux-test.c + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -lm + +# speed test +sha1-i386: sha1.c + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + +sha1: sha1.c + $(HOST_CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + +speed: sha1 sha1-i386 + time ./sha1 + time $(QEMU) ./sha1-i386 + +# vm86 test +runcom: runcom.c + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + +# NOTE: -fomit-frame-pointer is currently needed : this is a bug in libqemu +qruncom: qruncom.c ../i386-user/libqemu.a + $(CC) $(CFLAGS) -fomit-frame-pointer $(LDFLAGS) -I../target-i386 -I.. -I../i386-user \ + -o $@ $< -L../i386-user -lqemu -lm + +# arm test +hello-arm: hello-arm.o + arm-linux-ld -o $@ $< + +hello-arm.o: hello-arm.c + arm-linux-gcc -Wall -g -O2 -c -o $@ $< + +# XXX: find a way to compile easily a test for each arch +test2: + @for arch in i386 arm sparc ppc; do \ + ../$${arch}-user/qemu-$${arch} $${arch}/ls -l linux-test.c ; \ + done + +clean: + rm -f *~ *.o test-i386.out test-i386.ref qruncom $(TESTS) diff --git a/tools/ioemu/tests/hello-arm.c b/tools/ioemu/tests/hello-arm.c new file mode 100644 index 0000000000..f84e6cb368 --- /dev/null +++ b/tools/ioemu/tests/hello-arm.c @@ -0,0 +1,113 @@ +#define __NR_SYSCALL_BASE 0x900000 +#define __NR_exit1 (__NR_SYSCALL_BASE+ 1) +#define __NR_write (__NR_SYSCALL_BASE+ 4) + +#define __sys2(x) #x +#define __sys1(x) __sys2(x) + +#ifndef __syscall +#define __syscall(name) "swi\t" __sys1(__NR_##name) "\n\t" +#endif + +#define __syscall_return(type, res) \ +do { \ + return (type) (res); \ +} while (0) + +#define _syscall0(type,name) \ +type name(void) { \ + long __res; \ + __asm__ __volatile__ ( \ + __syscall(name) \ + "mov %0,r0" \ + :"=r" (__res) : : "r0","lr"); \ + __syscall_return(type,__res); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) { \ + long __res; \ + __asm__ __volatile__ ( \ + "mov\tr0,%1\n\t" \ + __syscall(name) \ + "mov %0,r0" \ + : "=r" (__res) \ + : "r" ((long)(arg1)) \ + : "r0","lr"); \ + __syscall_return(type,__res); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) { \ + long __res; \ + __asm__ __volatile__ ( \ + "mov\tr0,%1\n\t" \ + "mov\tr1,%2\n\t" \ + __syscall(name) \ + "mov\t%0,r0" \ + : "=r" (__res) \ + : "r" ((long)(arg1)),"r" ((long)(arg2)) \ + : "r0","r1","lr"); \ + __syscall_return(type,__res); \ +} + + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) { \ + long __res; \ + __asm__ __volatile__ ( \ + "mov\tr0,%1\n\t" \ + "mov\tr1,%2\n\t" \ + "mov\tr2,%3\n\t" \ + __syscall(name) \ + "mov\t%0,r0" \ + : "=r" (__res) \ + : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)) \ + : "r0","r1","r2","lr"); \ + __syscall_return(type,__res); \ +} + + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ + long __res; \ + __asm__ __volatile__ ( \ + "mov\tr0,%1\n\t" \ + "mov\tr1,%2\n\t" \ + "mov\tr2,%3\n\t" \ + "mov\tr3,%4\n\t" \ + __syscall(name) \ + "mov\t%0,r0" \ + : "=r" (__res) \ + : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)),"r" ((long)(arg4)) \ + : "r0","r1","r2","r3","lr"); \ + __syscall_return(type,__res); \ +} + + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \ +type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ + long __res; \ + __asm__ __volatile__ ( \ + "mov\tr0,%1\n\t" \ + "mov\tr1,%2\n\t" \ + "mov\tr2,%3\n\t" \ + "mov\tr3,%4\n\t" \ + "mov\tr4,%5\n\t" \ + __syscall(name) \ + "mov\t%0,r0" \ + : "=r" (__res) \ + : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)),"r" ((long)(arg4)), \ + "r" ((long)(arg5)) \ + : "r0","r1","r2","r3","r4","lr"); \ + __syscall_return(type,__res); \ +} + +_syscall1(int,exit1,int,status); +_syscall3(int,write,int,fd,const char *,buf, int, len); + +void _start(void) +{ + write(1, "Hello World\n", 12); + exit1(0); +} diff --git a/tools/ioemu/tests/hello-i386.c b/tools/ioemu/tests/hello-i386.c new file mode 100644 index 0000000000..e00245d3fe --- /dev/null +++ b/tools/ioemu/tests/hello-i386.c @@ -0,0 +1,26 @@ +#include + +extern inline volatile void exit(int status) +{ + int __res; + __asm__ volatile ("movl %%ecx,%%ebx\n"\ + "int $0x80" \ + : "=a" (__res) : "0" (__NR_exit),"c" ((long)(status))); +} + +extern inline int write(int fd, const char * buf, int len) +{ + int status; + __asm__ volatile ("pushl %%ebx\n"\ + "movl %%esi,%%ebx\n"\ + "int $0x80\n" \ + "popl %%ebx\n"\ + : "=a" (status) \ + : "0" (__NR_write),"S" ((long)(fd)),"c" ((long)(buf)),"d" ((long)(len))); +} + +void _start(void) +{ + write(1, "Hello World\n", 12); + exit(0); +} diff --git a/tools/ioemu/tests/linux-test.c b/tools/ioemu/tests/linux-test.c new file mode 100644 index 0000000000..6ca9029650 --- /dev/null +++ b/tools/ioemu/tests/linux-test.c @@ -0,0 +1,536 @@ +/* + * linux and CPU test + * + * Copyright (c) 2003 Fabrice Bellard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TESTPATH "/tmp/linux-test.tmp" +#define TESTPORT 7654 +#define STACK_SIZE 16384 + +void error1(const char *filename, int line, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d: ", filename, line); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(1); +} + +int __chk_error(const char *filename, int line, int ret) +{ + if (ret < 0) { + error1(filename, line, "%m (ret=%d, errno=%d)", + ret, errno); + } + return ret; +} + +#define error(fmt, args...) error1(__FILE__, __LINE__, fmt, ##args) + +#define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret)) + +/*******************************************************/ + +#define FILE_BUF_SIZE 300 + +void test_file(void) +{ + int fd, i, len, ret; + uint8_t buf[FILE_BUF_SIZE]; + uint8_t buf2[FILE_BUF_SIZE]; + uint8_t buf3[FILE_BUF_SIZE]; + char cur_dir[1024]; + struct stat st; + struct utimbuf tbuf; + struct iovec vecs[2]; + DIR *dir; + struct dirent *de; + + /* clean up, just in case */ + unlink(TESTPATH "/file1"); + unlink(TESTPATH "/file2"); + unlink(TESTPATH "/file3"); + rmdir(TESTPATH); + + if (getcwd(cur_dir, sizeof(cur_dir)) == NULL) + error("getcwd"); + + chk_error(mkdir(TESTPATH, 0755)); + + chk_error(chdir(TESTPATH)); + + /* open/read/write/close/readv/writev/lseek */ + + fd = chk_error(open("file1", O_WRONLY | O_TRUNC | O_CREAT, 0644)); + for(i=0;i < FILE_BUF_SIZE; i++) + buf[i] = i; + len = chk_error(write(fd, buf, FILE_BUF_SIZE / 2)); + if (len != (FILE_BUF_SIZE / 2)) + error("write"); + vecs[0].iov_base = buf + (FILE_BUF_SIZE / 2); + vecs[0].iov_len = 16; + vecs[1].iov_base = buf + (FILE_BUF_SIZE / 2) + 16; + vecs[1].iov_len = (FILE_BUF_SIZE / 2) - 16; + len = chk_error(writev(fd, vecs, 2)); + if (len != (FILE_BUF_SIZE / 2)) + error("writev"); + chk_error(close(fd)); + + chk_error(rename("file1", "file2")); + + fd = chk_error(open("file2", O_RDONLY)); + + len = chk_error(read(fd, buf2, FILE_BUF_SIZE)); + if (len != FILE_BUF_SIZE) + error("read"); + if (memcmp(buf, buf2, FILE_BUF_SIZE) != 0) + error("memcmp"); + +#define FOFFSET 16 + ret = chk_error(lseek(fd, FOFFSET, SEEK_SET)); + if (ret != 16) + error("lseek"); + vecs[0].iov_base = buf3; + vecs[0].iov_len = 32; + vecs[1].iov_base = buf3 + 32; + vecs[1].iov_len = FILE_BUF_SIZE - FOFFSET - 32; + len = chk_error(readv(fd, vecs, 2)); + if (len != FILE_BUF_SIZE - FOFFSET) + error("readv"); + if (memcmp(buf + FOFFSET, buf3, FILE_BUF_SIZE - FOFFSET) != 0) + error("memcmp"); + + chk_error(close(fd)); + + /* access */ + chk_error(access("file2", R_OK)); + + /* stat/chmod/utime/truncate */ + + chk_error(chmod("file2", 0600)); + tbuf.actime = 1001; + tbuf.modtime = 1000; + chk_error(truncate("file2", 100)); + chk_error(utime("file2", &tbuf)); + chk_error(stat("file2", &st)); + if (st.st_size != 100) + error("stat size"); + if (!S_ISREG(st.st_mode)) + error("stat mode"); + if ((st.st_mode & 0777) != 0600) + error("stat mode2"); + if (st.st_atime != 1001 || + st.st_mtime != 1000) + error("stat time"); + + chk_error(stat(TESTPATH, &st)); + if (!S_ISDIR(st.st_mode)) + error("stat mode"); + + /* fstat */ + fd = chk_error(open("file2", O_RDWR)); + chk_error(ftruncate(fd, 50)); + chk_error(fstat(fd, &st)); + chk_error(close(fd)); + + if (st.st_size != 50) + error("stat size"); + if (!S_ISREG(st.st_mode)) + error("stat mode"); + + /* symlink/lstat */ + chk_error(symlink("file2", "file3")); + chk_error(lstat("file3", &st)); + if (!S_ISLNK(st.st_mode)) + error("stat mode"); + + /* getdents */ + dir = opendir(TESTPATH); + if (!dir) + error("opendir"); + len = 0; + for(;;) { + de = readdir(dir); + if (!de) + break; + if (strcmp(de->d_name, ".") != 0 && + strcmp(de->d_name, "..") != 0 && + strcmp(de->d_name, "file2") != 0 && + strcmp(de->d_name, "file3") != 0) + error("readdir"); + len++; + } + closedir(dir); + if (len != 4) + error("readdir"); + + chk_error(unlink("file3")); + chk_error(unlink("file2")); + chk_error(chdir(cur_dir)); + chk_error(rmdir(TESTPATH)); +} + +void test_fork(void) +{ + int pid, status; + + pid = chk_error(fork()); + if (pid == 0) { + /* child */ + exit(2); + } + chk_error(waitpid(pid, &status, 0)); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 2) + error("waitpid status=0x%x", status); +} + +void test_time(void) +{ + struct timeval tv, tv2; + struct timespec ts, rem; + struct rusage rusg1, rusg2; + int ti, i; + + chk_error(gettimeofday(&tv, NULL)); + rem.tv_sec = 1; + ts.tv_sec = 0; + ts.tv_nsec = 20 * 1000000; + chk_error(nanosleep(&ts, &rem)); + if (rem.tv_sec != 1) + error("nanosleep"); + chk_error(gettimeofday(&tv2, NULL)); + ti = tv2.tv_sec - tv.tv_sec; + if (ti >= 2) + error("gettimeofday"); + + chk_error(getrusage(RUSAGE_SELF, &rusg1)); + for(i = 0;i < 10000; i++); + chk_error(getrusage(RUSAGE_SELF, &rusg2)); + if ((rusg2.ru_utime.tv_sec - rusg1.ru_utime.tv_sec) < 0 || + (rusg2.ru_stime.tv_sec - rusg1.ru_stime.tv_sec) < 0) + error("getrusage"); +} + +void pstrcpy(char *buf, int buf_size, const char *str) +{ + int c; + char *q = buf; + + if (buf_size <= 0) + return; + + for(;;) { + c = *str++; + if (c == 0 || q >= buf + buf_size - 1) + break; + *q++ = c; + } + *q = '\0'; +} + +/* strcat and truncate. */ +char *pstrcat(char *buf, int buf_size, const char *s) +{ + int len; + len = strlen(buf); + if (len < buf_size) + pstrcpy(buf + len, buf_size - len, s); + return buf; +} + +int server_socket(void) +{ + int val, fd; + struct sockaddr_in sockaddr; + + /* server socket */ + fd = chk_error(socket(PF_INET, SOCK_STREAM, 0)); + + val = 1; + chk_error(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val))); + + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = htons(TESTPORT); + sockaddr.sin_addr.s_addr = 0; + chk_error(bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))); + chk_error(listen(fd, 0)); + return fd; + +} + +int client_socket(void) +{ + int fd; + struct sockaddr_in sockaddr; + + /* server socket */ + fd = chk_error(socket(PF_INET, SOCK_STREAM, 0)); + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = htons(TESTPORT); + inet_aton("127.0.0.1", &sockaddr.sin_addr); + chk_error(connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))); + return fd; +} + +const char socket_msg[] = "hello socket\n"; + +void test_socket(void) +{ + int server_fd, client_fd, fd, pid, ret, val; + struct sockaddr_in sockaddr; + socklen_t len; + char buf[512]; + + server_fd = server_socket(); + + /* test a few socket options */ + len = sizeof(val); + chk_error(getsockopt(server_fd, SOL_SOCKET, SO_TYPE, &val, &len)); + if (val != SOCK_STREAM) + error("getsockopt"); + + pid = chk_error(fork()); + if (pid == 0) { + client_fd = client_socket(); + send(client_fd, socket_msg, sizeof(socket_msg), 0); + close(client_fd); + exit(0); + } + len = sizeof(sockaddr); + fd = chk_error(accept(server_fd, (struct sockaddr *)&sockaddr, &len)); + + ret = chk_error(recv(fd, buf, sizeof(buf), 0)); + if (ret != sizeof(socket_msg)) + error("recv"); + if (memcmp(buf, socket_msg, sizeof(socket_msg)) != 0) + error("socket_msg"); + chk_error(close(fd)); + chk_error(close(server_fd)); +} + +#define WCOUNT_MAX 512 + +void test_pipe(void) +{ + fd_set rfds, wfds; + int fds[2], fd_max, ret; + uint8_t ch; + int wcount, rcount; + + chk_error(pipe(fds)); + chk_error(fcntl(fds[0], F_SETFL, O_NONBLOCK)); + chk_error(fcntl(fds[1], F_SETFL, O_NONBLOCK)); + wcount = 0; + rcount = 0; + for(;;) { + FD_ZERO(&rfds); + fd_max = fds[0]; + FD_SET(fds[0], &rfds); + + FD_ZERO(&wfds); + FD_SET(fds[1], &wfds); + if (fds[1] > fd_max) + fd_max = fds[1]; + + ret = chk_error(select(fd_max + 1, &rfds, &wfds, NULL, NULL)); + if (ret > 0) { + if (FD_ISSET(fds[0], &rfds)) { + chk_error(read(fds[0], &ch, 1)); + rcount++; + if (rcount >= WCOUNT_MAX) + break; + } + if (FD_ISSET(fds[1], &wfds)) { + ch = 'a'; + chk_error(write(fds[0], &ch, 1)); + wcount++; + } + } + } + chk_error(close(fds[0])); + chk_error(close(fds[1])); +} + +int thread1_res; +int thread2_res; + +int thread1_func(void *arg) +{ + int i; + for(i=0;i<5;i++) { + thread1_res++; + usleep(10 * 1000); + } + return 0; +} + +int thread2_func(void *arg) +{ + int i; + for(i=0;i<6;i++) { + thread2_res++; + usleep(10 * 1000); + } + return 0; +} + +void test_clone(void) +{ + uint8_t *stack1, *stack2; + int pid1, pid2, status1, status2; + + stack1 = malloc(STACK_SIZE); + pid1 = chk_error(clone(thread1_func, stack1 + STACK_SIZE, + CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello1")); + + stack2 = malloc(STACK_SIZE); + pid2 = chk_error(clone(thread2_func, stack2 + STACK_SIZE, + CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello2")); + + while (waitpid(pid1, &status1, 0) != pid1); + while (waitpid(pid2, &status2, 0) != pid2); + if (thread1_res != 5 || + thread2_res != 6) + error("clone"); +} + +/***********************************/ + +volatile int alarm_count; +jmp_buf jmp_env; + +void sig_alarm(int sig) +{ + if (sig != SIGALRM) + error("signal"); + alarm_count++; +} + +void sig_segv(int sig, siginfo_t *info, void *puc) +{ + if (sig != SIGSEGV) + error("signal"); + longjmp(jmp_env, 1); +} + +void test_signal(void) +{ + struct sigaction act; + struct itimerval it, oit; + + /* timer test */ + + alarm_count = 0; + + act.sa_handler = sig_alarm; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + chk_error(sigaction(SIGALRM, &act, NULL)); + + it.it_interval.tv_sec = 0; + it.it_interval.tv_usec = 10 * 1000; + it.it_value.tv_sec = 0; + it.it_value.tv_usec = 10 * 1000; + chk_error(setitimer(ITIMER_REAL, &it, NULL)); + chk_error(getitimer(ITIMER_REAL, &oit)); + if (oit.it_value.tv_sec != it.it_value.tv_sec || + oit.it_value.tv_usec != it.it_value.tv_usec) + error("itimer"); + + while (alarm_count < 5) { + usleep(10 * 1000); + } + + it.it_interval.tv_sec = 0; + it.it_interval.tv_usec = 0; + it.it_value.tv_sec = 0; + it.it_value.tv_usec = 0; + memset(&oit, 0xff, sizeof(oit)); + chk_error(setitimer(ITIMER_REAL, &it, &oit)); + if (oit.it_value.tv_sec != 0 || + oit.it_value.tv_usec != 10 * 1000) + error("setitimer"); + + /* SIGSEGV test */ + act.sa_sigaction = sig_segv; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_SIGINFO; + chk_error(sigaction(SIGSEGV, &act, NULL)); + if (setjmp(jmp_env) == 0) { + *(uint8_t *)0 = 0; + } + + act.sa_handler = SIG_DFL; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + chk_error(sigaction(SIGSEGV, &act, NULL)); +} + +#define SHM_SIZE 32768 + +void test_shm(void) +{ + void *ptr; + int shmid; + + shmid = chk_error(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0777)); + ptr = shmat(shmid, NULL, 0); + if (!ptr) + error("shmat"); + + memset(ptr, 0, SHM_SIZE); + + chk_error(shmctl(shmid, IPC_RMID, 0)); + chk_error(shmdt(ptr)); +} + +int main(int argc, char **argv) +{ + test_file(); + test_fork(); + test_time(); + test_socket(); + // test_clone(); + test_signal(); + test_shm(); + return 0; +} diff --git a/tools/ioemu/tests/pi_10.com b/tools/ioemu/tests/pi_10.com new file mode 100644 index 0000000000000000000000000000000000000000..8993ba1a51bbc2aaddc3aa99ceea37ab3bf9ea9e GIT binary patch literal 54 zcmV-60LlM|6SaSi!9cr&CiAO|!E5OPMfdfRtCIKOQkA$004Db(1I1kv)#B#&Gz2h` MtF!{mAxm}F!x~T=Hvj+t literal 0 HcmV?d00001 diff --git a/tools/ioemu/tests/qruncom.c b/tools/ioemu/tests/qruncom.c new file mode 100644 index 0000000000..fcc069f6d0 --- /dev/null +++ b/tools/ioemu/tests/qruncom.c @@ -0,0 +1,308 @@ +/* + * Example of use of user mode libqemu: launch a basic .com DOS + * executable + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cpu.h" + +//#define SIGTEST + +CPUState *cpu_single_env = NULL; + +void cpu_outb(CPUState *env, int addr, int val) +{ + fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val); +} + +void cpu_outw(CPUState *env, int addr, int val) +{ + fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val); +} + +void cpu_outl(CPUState *env, int addr, int val) +{ + fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val); +} + +int cpu_inb(CPUState *env, int addr) +{ + fprintf(stderr, "inb: port=0x%04x\n", addr); + return 0; +} + +int cpu_inw(CPUState *env, int addr) +{ + fprintf(stderr, "inw: port=0x%04x\n", addr); + return 0; +} + +int cpu_inl(CPUState *env, int addr) +{ + fprintf(stderr, "inl: port=0x%04x\n", addr); + return 0; +} + +int cpu_get_pic_interrupt(CPUState *env) +{ + return -1; +} + +uint64_t cpu_get_tsc(CPUState *env) +{ + return 0; +} + +static void set_gate(void *ptr, unsigned int type, unsigned int dpl, + unsigned long addr, unsigned int sel) +{ + unsigned int e1, e2; + e1 = (addr & 0xffff) | (sel << 16); + e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); + stl((uint8_t *)ptr, e1); + stl((uint8_t *)ptr + 4, e2); +} + +uint64_t idt_table[256]; + +/* only dpl matters as we do only user space emulation */ +static void set_idt(int n, unsigned int dpl) +{ + set_gate(idt_table + n, 0, dpl, 0, 0); +} + +void qemu_free(void *ptr) +{ + free(ptr); +} + +void *qemu_malloc(size_t size) +{ + return malloc(size); +} + +void qemu_printf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); +} + +/* XXX: this is a bug in helper2.c */ +int errno; + +/**********************************************/ + +#define COM_BASE_ADDR 0x10100 + +void usage(void) +{ + printf("qruncom version 0.1 (c) 2003 Fabrice Bellard\n" + "usage: qruncom file.com\n" + "user mode libqemu demo: run simple .com DOS executables\n"); + exit(1); +} + +static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg) +{ + return (uint8_t *)((seg << 4) + (reg & 0xffff)); +} + +static inline void pushw(CPUState *env, int val) +{ + env->regs[R_ESP] = (env->regs[R_ESP] & ~0xffff) | ((env->regs[R_ESP] - 2) & 0xffff); + *(uint16_t *)seg_to_linear(env->segs[R_SS].selector, env->regs[R_ESP]) = val; +} + +static void host_segv_handler(int host_signum, siginfo_t *info, + void *puc) +{ + if (cpu_signal_handler(host_signum, info, puc)) { + return; + } + abort(); +} + +int main(int argc, char **argv) +{ + uint8_t *vm86_mem; + const char *filename; + int fd, ret, seg; + CPUState *env; + + if (argc != 2) + usage(); + filename = argv[1]; + + vm86_mem = mmap((void *)0x00000000, 0x110000, + PROT_WRITE | PROT_READ | PROT_EXEC, + MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); + if (vm86_mem == MAP_FAILED) { + perror("mmap"); + exit(1); + } + + /* load the MSDOS .com executable */ + fd = open(filename, O_RDONLY); + if (fd < 0) { + perror(filename); + exit(1); + } + ret = read(fd, vm86_mem + COM_BASE_ADDR, 65536 - 256); + if (ret < 0) { + perror("read"); + exit(1); + } + close(fd); + + /* install exception handler for CPU emulator */ + { + struct sigaction act; + + sigfillset(&act.sa_mask); + act.sa_flags = SA_SIGINFO; + // act.sa_flags |= SA_ONSTACK; + + act.sa_sigaction = host_segv_handler; + sigaction(SIGSEGV, &act, NULL); + sigaction(SIGBUS, &act, NULL); +#if defined (TARGET_I386) && defined(USE_CODE_COPY) + sigaction(SIGFPE, &act, NULL); +#endif + } + + // cpu_set_log(CPU_LOG_TB_IN_ASM | CPU_LOG_TB_OUT_ASM | CPU_LOG_EXEC); + + env = cpu_init(); + + /* disable code copy to simplify debugging */ + code_copy_enabled = 0; + + /* set user mode state (XXX: should be done automatically by + cpu_init ?) */ + env->user_mode_only = 1; + + cpu_x86_set_cpl(env, 3); + + env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK; + /* NOTE: hflags duplicates some of the virtual CPU state */ + env->hflags |= HF_PE_MASK | VM_MASK; + + /* flags setup : we activate the IRQs by default as in user + mode. We also activate the VM86 flag to run DOS code */ + env->eflags |= IF_MASK | VM_MASK; + + /* init basic registers */ + env->eip = 0x100; + env->regs[R_ESP] = 0xfffe; + seg = (COM_BASE_ADDR - 0x100) >> 4; + + cpu_x86_load_seg_cache(env, R_CS, seg, + (uint8_t *)(seg << 4), 0xffff, 0); + cpu_x86_load_seg_cache(env, R_SS, seg, + (uint8_t *)(seg << 4), 0xffff, 0); + cpu_x86_load_seg_cache(env, R_DS, seg, + (uint8_t *)(seg << 4), 0xffff, 0); + cpu_x86_load_seg_cache(env, R_ES, seg, + (uint8_t *)(seg << 4), 0xffff, 0); + cpu_x86_load_seg_cache(env, R_FS, seg, + (uint8_t *)(seg << 4), 0xffff, 0); + cpu_x86_load_seg_cache(env, R_GS, seg, + (uint8_t *)(seg << 4), 0xffff, 0); + + /* exception support */ + env->idt.base = (void *)idt_table; + env->idt.limit = sizeof(idt_table) - 1; + set_idt(0, 0); + set_idt(1, 0); + set_idt(2, 0); + set_idt(3, 3); + set_idt(4, 3); + set_idt(5, 3); + set_idt(6, 0); + set_idt(7, 0); + set_idt(8, 0); + set_idt(9, 0); + set_idt(10, 0); + set_idt(11, 0); + set_idt(12, 0); + set_idt(13, 0); + set_idt(14, 0); + set_idt(15, 0); + set_idt(16, 0); + set_idt(17, 0); + set_idt(18, 0); + set_idt(19, 0); + + /* put return code */ + *seg_to_linear(env->segs[R_CS].selector, 0) = 0xb4; /* mov ah, $0 */ + *seg_to_linear(env->segs[R_CS].selector, 1) = 0x00; + *seg_to_linear(env->segs[R_CS].selector, 2) = 0xcd; /* int $0x21 */ + *seg_to_linear(env->segs[R_CS].selector, 3) = 0x21; + pushw(env, 0x0000); + + /* the value of these registers seem to be assumed by pi_10.com */ + env->regs[R_ESI] = 0x100; + env->regs[R_ECX] = 0xff; + env->regs[R_EBP] = 0x0900; + env->regs[R_EDI] = 0xfffe; + + /* inform the emulator of the mmaped memory */ + page_set_flags(0x00000000, 0x110000, + PAGE_WRITE | PAGE_READ | PAGE_EXEC | PAGE_VALID); + + for(;;) { + ret = cpu_x86_exec(env); + switch(ret) { + case EXCP0D_GPF: + { + int int_num, ah; + int_num = *(env->segs[R_CS].base + env->eip + 1); + if (int_num != 0x21) + goto unknown_int; + ah = (env->regs[R_EAX] >> 8) & 0xff; + switch(ah) { + case 0x00: /* exit */ + exit(0); + case 0x02: /* write char */ + { + uint8_t c = env->regs[R_EDX]; + write(1, &c, 1); + } + break; + case 0x09: /* write string */ + { + uint8_t c; + for(;;) { + c = *seg_to_linear(env->segs[R_DS].selector, env->regs[R_EAX]); + if (c == '$') + break; + write(1, &c, 1); + } + env->regs[R_EAX] = (env->regs[R_EAX] & ~0xff) | '$'; + } + break; + default: + unknown_int: + fprintf(stderr, "unsupported int 0x%02x\n", int_num); + cpu_dump_state(env, stderr, 0); + // exit(1); + } + env->eip += 2; + } + break; + default: + fprintf(stderr, "unhandled cpu_exec return code (0x%x)\n", ret); + cpu_dump_state(env, stderr, 0); + exit(1); + } + } +} diff --git a/tools/ioemu/tests/runcom.c b/tools/ioemu/tests/runcom.c new file mode 100644 index 0000000000..43deeca098 --- /dev/null +++ b/tools/ioemu/tests/runcom.c @@ -0,0 +1,195 @@ +/* + * Simple example of use of vm86: launch a basic .com DOS executable + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//#define SIGTEST + +#undef __syscall_return +#define __syscall_return(type, res) \ +do { \ + return (type) (res); \ +} while (0) + +_syscall2(int, vm86, int, func, struct vm86plus_struct *, v86) + +#define COM_BASE_ADDR 0x10100 + +void usage(void) +{ + printf("runcom version 0.1 (c) 2003 Fabrice Bellard\n" + "usage: runcom file.com\n" + "VM86 Run simple .com DOS executables (linux vm86 test mode)\n"); + exit(1); +} + +static inline void set_bit(uint8_t *a, unsigned int bit) +{ + a[bit / 8] |= (1 << (bit % 8)); +} + +static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg) +{ + return (uint8_t *)((seg << 4) + (reg & 0xffff)); +} + +static inline void pushw(struct vm86_regs *r, int val) +{ + r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff); + *(uint16_t *)seg_to_linear(r->ss, r->esp) = val; +} + +void dump_regs(struct vm86_regs *r) +{ + fprintf(stderr, + "EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n" + "ESI=%08lx EDI=%08lx EBP=%08lx ESP=%08lx\n" + "EIP=%08lx EFL=%08lx\n" + "CS=%04x DS=%04x ES=%04x SS=%04x FS=%04x GS=%04x\n", + r->eax, r->ebx, r->ecx, r->edx, r->esi, r->edi, r->ebp, r->esp, + r->eip, r->eflags, + r->cs, r->ds, r->es, r->ss, r->fs, r->gs); +} + +#ifdef SIGTEST +void alarm_handler(int sig) +{ + fprintf(stderr, "alarm signal=%d\n", sig); + alarm(1); +} +#endif + +int main(int argc, char **argv) +{ + uint8_t *vm86_mem; + const char *filename; + int fd, ret, seg; + struct vm86plus_struct ctx; + struct vm86_regs *r; + + if (argc != 2) + usage(); + filename = argv[1]; + + vm86_mem = mmap((void *)0x00000000, 0x110000, + PROT_WRITE | PROT_READ | PROT_EXEC, + MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); + if (vm86_mem == MAP_FAILED) { + perror("mmap"); + exit(1); + } +#ifdef SIGTEST + { + struct sigaction act; + + act.sa_handler = alarm_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + sigaction(SIGALRM, &act, NULL); + alarm(1); + } +#endif + + /* load the MSDOS .com executable */ + fd = open(filename, O_RDONLY); + if (fd < 0) { + perror(filename); + exit(1); + } + ret = read(fd, vm86_mem + COM_BASE_ADDR, 65536 - 256); + if (ret < 0) { + perror("read"); + exit(1); + } + close(fd); + + memset(&ctx, 0, sizeof(ctx)); + /* init basic registers */ + r = &ctx.regs; + r->eip = 0x100; + r->esp = 0xfffe; + seg = (COM_BASE_ADDR - 0x100) >> 4; + r->cs = seg; + r->ss = seg; + r->ds = seg; + r->es = seg; + r->fs = seg; + r->gs = seg; + r->eflags = VIF_MASK; + + /* put return code */ + set_bit((uint8_t *)&ctx.int_revectored, 0x21); + *seg_to_linear(r->cs, 0) = 0xb4; /* mov ah, $0 */ + *seg_to_linear(r->cs, 1) = 0x00; + *seg_to_linear(r->cs, 2) = 0xcd; /* int $0x21 */ + *seg_to_linear(r->cs, 3) = 0x21; + pushw(&ctx.regs, 0x0000); + + /* the value of these registers seem to be assumed by pi_10.com */ + r->esi = 0x100; + r->ecx = 0xff; + r->ebp = 0x0900; + r->edi = 0xfffe; + + for(;;) { + ret = vm86(VM86_ENTER, &ctx); + switch(VM86_TYPE(ret)) { + case VM86_INTx: + { + int int_num, ah; + + int_num = VM86_ARG(ret); + if (int_num != 0x21) + goto unknown_int; + ah = (r->eax >> 8) & 0xff; + switch(ah) { + case 0x00: /* exit */ + exit(0); + case 0x02: /* write char */ + { + uint8_t c = r->edx; + write(1, &c, 1); + } + break; + case 0x09: /* write string */ + { + uint8_t c; + for(;;) { + c = *seg_to_linear(r->ds, r->edx); + if (c == '$') + break; + write(1, &c, 1); + } + r->eax = (r->eax & ~0xff) | '$'; + } + break; + default: + unknown_int: + fprintf(stderr, "unsupported int 0x%02x\n", int_num); + dump_regs(&ctx.regs); + // exit(1); + } + } + break; + case VM86_SIGNAL: + /* a signal came, we just ignore that */ + break; + case VM86_STI: + break; + default: + fprintf(stderr, "unhandled vm86 return code (0x%x)\n", ret); + dump_regs(&ctx.regs); + exit(1); + } + } +} diff --git a/tools/ioemu/tests/sha1.c b/tools/ioemu/tests/sha1.c new file mode 100644 index 0000000000..31b001920d --- /dev/null +++ b/tools/ioemu/tests/sha1.c @@ -0,0 +1,242 @@ + +/* from valgrind tests */ + +/* ================ sha1.c ================ */ +/* +SHA-1 in C +By Steve Reid +100% Public Domain + +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */ +/* #define SHA1HANDSOFF * Copies data before messing with it. */ + +#define SHA1HANDSOFF + +#include +#include +#include /* for u_int*_t */ + +/* ================ sha1.h ================ */ +/* +SHA-1 in C +By Steve Reid +100% Public Domain +*/ + +typedef struct { + u_int32_t state[5]; + u_int32_t count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64]); +void SHA1Init(SHA1_CTX* context); +void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len); +void SHA1Final(unsigned char digest[20], SHA1_CTX* context); +/* ================ end of sha1.h ================ */ +#include + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#if BYTE_ORDER == LITTLE_ENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#elif BYTE_ORDER == BIG_ENDIAN +#define blk0(i) block->l[i] +#else +#error "Endianness not defined!" +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64]) +{ +u_int32_t a, b, c, d, e; +typedef union { + unsigned char c[64]; + u_int32_t l[16]; +} CHAR64LONG16; +#ifdef SHA1HANDSOFF +CHAR64LONG16 block[1]; /* use array to appear as a pointer */ + memcpy(block, buffer, 64); +#else + /* The following had better never be used because it causes the + * pointer-to-const buffer to be cast into a pointer to non-const. + * And the result is written through. I threw a "const" in, hoping + * this will cause a diagnostic. + */ +CHAR64LONG16* block = (const CHAR64LONG16*)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +#ifdef SHA1HANDSOFF + memset(block, '\0', sizeof(block)); +#endif +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init(SHA1_CTX* context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len) +{ +u_int32_t i; +u_int32_t j; + + j = context->count[0]; + if ((context->count[0] += len << 3) < j) + context->count[1]++; + context->count[1] += (len>>29); + j = (j >> 3) & 63; + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ + +void SHA1Final(unsigned char digest[20], SHA1_CTX* context) +{ +unsigned i; +unsigned char finalcount[8]; +unsigned char c; + +#if 0 /* untested "improvement" by DHR */ + /* Convert context->count to a sequence of bytes + * in finalcount. Second element first, but + * big-endian order within element. + * But we do it all backwards. + */ + unsigned char *fcp = &finalcount[8]; + + for (i = 0; i < 2; i++) + { + u_int32_t t = context->count[i]; + int j; + + for (j = 0; j < 4; t >>= 8, j++) + *--fcp = (unsigned char) t + } +#else + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } +#endif + c = 0200; + SHA1Update(context, &c, 1); + while ((context->count[0] & 504) != 448) { + c = 0000; + SHA1Update(context, &c, 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + /* Wipe variables */ + memset(context, '\0', sizeof(*context)); + memset(&finalcount, '\0', sizeof(finalcount)); +} +/* ================ end of sha1.c ================ */ + +#define BUFSIZE 4096 + +int +main(int argc, char **argv) +{ + SHA1_CTX ctx; + unsigned char hash[20], buf[BUFSIZE]; + int i; + + for(i=0;i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TEST_CMOV 0 +#define TEST_FCOMI 0 +//#define LINUX_VM86_IOPL_FIX +//#define TEST_P4_FLAGS + +#define xglue(x, y) x ## y +#define glue(x, y) xglue(x, y) +#define stringify(s) tostring(s) +#define tostring(s) #s + +#define CC_C 0x0001 +#define CC_P 0x0004 +#define CC_A 0x0010 +#define CC_Z 0x0040 +#define CC_S 0x0080 +#define CC_O 0x0800 + +#define __init_call __attribute__ ((unused,__section__ (".initcall.init"))) + +static void *call_start __init_call = NULL; + +#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A) + +#define OP add +#include "test-i386.h" + +#define OP sub +#include "test-i386.h" + +#define OP xor +#include "test-i386.h" + +#define OP and +#include "test-i386.h" + +#define OP or +#include "test-i386.h" + +#define OP cmp +#include "test-i386.h" + +#define OP adc +#define OP_CC +#include "test-i386.h" + +#define OP sbb +#define OP_CC +#include "test-i386.h" + +#define OP inc +#define OP_CC +#define OP1 +#include "test-i386.h" + +#define OP dec +#define OP_CC +#define OP1 +#include "test-i386.h" + +#define OP neg +#define OP_CC +#define OP1 +#include "test-i386.h" + +#define OP not +#define OP_CC +#define OP1 +#include "test-i386.h" + +#undef CC_MASK +#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O) + +#define OP shl +#include "test-i386-shift.h" + +#define OP shr +#include "test-i386-shift.h" + +#define OP sar +#include "test-i386-shift.h" + +#define OP rol +#include "test-i386-shift.h" + +#define OP ror +#include "test-i386-shift.h" + +#define OP rcr +#define OP_CC +#include "test-i386-shift.h" + +#define OP rcl +#define OP_CC +#include "test-i386-shift.h" + +#define OP shld +#define OP_SHIFTD +#define OP_NOBYTE +#include "test-i386-shift.h" + +#define OP shrd +#define OP_SHIFTD +#define OP_NOBYTE +#include "test-i386-shift.h" + +/* XXX: should be more precise ? */ +#undef CC_MASK +#define CC_MASK (CC_C) + +#define OP bt +#define OP_NOBYTE +#include "test-i386-shift.h" + +#define OP bts +#define OP_NOBYTE +#include "test-i386-shift.h" + +#define OP btr +#define OP_NOBYTE +#include "test-i386-shift.h" + +#define OP btc +#define OP_NOBYTE +#include "test-i386-shift.h" + +/* lea test (modrm support) */ +#define TEST_LEA(STR)\ +{\ + asm("leal " STR ", %0"\ + : "=r" (res)\ + : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\ + printf("lea %s = %08x\n", STR, res);\ +} + +#define TEST_LEA16(STR)\ +{\ + asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\ + : "=wq" (res)\ + : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\ + printf("lea %s = %08x\n", STR, res);\ +} + + +void test_lea(void) +{ + int eax, ebx, ecx, edx, esi, edi, res; + eax = 0x0001; + ebx = 0x0002; + ecx = 0x0004; + edx = 0x0008; + esi = 0x0010; + edi = 0x0020; + + TEST_LEA("0x4000"); + + TEST_LEA("(%%eax)"); + TEST_LEA("(%%ebx)"); + TEST_LEA("(%%ecx)"); + TEST_LEA("(%%edx)"); + TEST_LEA("(%%esi)"); + TEST_LEA("(%%edi)"); + + TEST_LEA("0x40(%%eax)"); + TEST_LEA("0x40(%%ebx)"); + TEST_LEA("0x40(%%ecx)"); + TEST_LEA("0x40(%%edx)"); + TEST_LEA("0x40(%%esi)"); + TEST_LEA("0x40(%%edi)"); + + TEST_LEA("0x4000(%%eax)"); + TEST_LEA("0x4000(%%ebx)"); + TEST_LEA("0x4000(%%ecx)"); + TEST_LEA("0x4000(%%edx)"); + TEST_LEA("0x4000(%%esi)"); + TEST_LEA("0x4000(%%edi)"); + + TEST_LEA("(%%eax, %%ecx)"); + TEST_LEA("(%%ebx, %%edx)"); + TEST_LEA("(%%ecx, %%ecx)"); + TEST_LEA("(%%edx, %%ecx)"); + TEST_LEA("(%%esi, %%ecx)"); + TEST_LEA("(%%edi, %%ecx)"); + + TEST_LEA("0x40(%%eax, %%ecx)"); + TEST_LEA("0x4000(%%ebx, %%edx)"); + + TEST_LEA("(%%ecx, %%ecx, 2)"); + TEST_LEA("(%%edx, %%ecx, 4)"); + TEST_LEA("(%%esi, %%ecx, 8)"); + + TEST_LEA("(,%%eax, 2)"); + TEST_LEA("(,%%ebx, 4)"); + TEST_LEA("(,%%ecx, 8)"); + + TEST_LEA("0x40(,%%eax, 2)"); + TEST_LEA("0x40(,%%ebx, 4)"); + TEST_LEA("0x40(,%%ecx, 8)"); + + + TEST_LEA("-10(%%ecx, %%ecx, 2)"); + TEST_LEA("-10(%%edx, %%ecx, 4)"); + TEST_LEA("-10(%%esi, %%ecx, 8)"); + + TEST_LEA("0x4000(%%ecx, %%ecx, 2)"); + TEST_LEA("0x4000(%%edx, %%ecx, 4)"); + TEST_LEA("0x4000(%%esi, %%ecx, 8)"); + + /* limited 16 bit addressing test */ + TEST_LEA16("0x4000"); + TEST_LEA16("(%%bx)"); + TEST_LEA16("(%%si)"); + TEST_LEA16("(%%di)"); + TEST_LEA16("0x40(%%bx)"); + TEST_LEA16("0x40(%%si)"); + TEST_LEA16("0x40(%%di)"); + TEST_LEA16("0x4000(%%bx)"); + TEST_LEA16("0x4000(%%si)"); + TEST_LEA16("(%%bx,%%si)"); + TEST_LEA16("(%%bx,%%di)"); + TEST_LEA16("0x40(%%bx,%%si)"); + TEST_LEA16("0x40(%%bx,%%di)"); + TEST_LEA16("0x4000(%%bx,%%si)"); + TEST_LEA16("0x4000(%%bx,%%di)"); +} + +#define TEST_JCC(JCC, v1, v2)\ +{\ + int res;\ + asm("movl $1, %0\n\t"\ + "cmpl %2, %1\n\t"\ + "j" JCC " 1f\n\t"\ + "movl $0, %0\n\t"\ + "1:\n\t"\ + : "=r" (res)\ + : "r" (v1), "r" (v2));\ + printf("%-10s %d\n", "j" JCC, res);\ +\ + asm("movl $0, %0\n\t"\ + "cmpl %2, %1\n\t"\ + "set" JCC " %b0\n\t"\ + : "=r" (res)\ + : "r" (v1), "r" (v2));\ + printf("%-10s %d\n", "set" JCC, res);\ + if (TEST_CMOV) {\ + asm("movl $0x12345678, %0\n\t"\ + "cmpl %2, %1\n\t"\ + "cmov" JCC "l %3, %0\n\t"\ + : "=r" (res)\ + : "r" (v1), "r" (v2), "m" (1));\ + printf("%-10s R=0x%08x\n", "cmov" JCC "l", res);\ + asm("movl $0x12345678, %0\n\t"\ + "cmpl %2, %1\n\t"\ + "cmov" JCC "w %w3, %w0\n\t"\ + : "=r" (res)\ + : "r" (v1), "r" (v2), "r" (1));\ + printf("%-10s R=0x%08x\n", "cmov" JCC "w", res);\ + } \ +} + +/* various jump tests */ +void test_jcc(void) +{ + TEST_JCC("ne", 1, 1); + TEST_JCC("ne", 1, 0); + + TEST_JCC("e", 1, 1); + TEST_JCC("e", 1, 0); + + TEST_JCC("l", 1, 1); + TEST_JCC("l", 1, 0); + TEST_JCC("l", 1, -1); + + TEST_JCC("le", 1, 1); + TEST_JCC("le", 1, 0); + TEST_JCC("le", 1, -1); + + TEST_JCC("ge", 1, 1); + TEST_JCC("ge", 1, 0); + TEST_JCC("ge", -1, 1); + + TEST_JCC("g", 1, 1); + TEST_JCC("g", 1, 0); + TEST_JCC("g", 1, -1); + + TEST_JCC("b", 1, 1); + TEST_JCC("b", 1, 0); + TEST_JCC("b", 1, -1); + + TEST_JCC("be", 1, 1); + TEST_JCC("be", 1, 0); + TEST_JCC("be", 1, -1); + + TEST_JCC("ae", 1, 1); + TEST_JCC("ae", 1, 0); + TEST_JCC("ae", 1, -1); + + TEST_JCC("a", 1, 1); + TEST_JCC("a", 1, 0); + TEST_JCC("a", 1, -1); + + + TEST_JCC("p", 1, 1); + TEST_JCC("p", 1, 0); + + TEST_JCC("np", 1, 1); + TEST_JCC("np", 1, 0); + + TEST_JCC("o", 0x7fffffff, 0); + TEST_JCC("o", 0x7fffffff, -1); + + TEST_JCC("no", 0x7fffffff, 0); + TEST_JCC("no", 0x7fffffff, -1); + + TEST_JCC("s", 0, 1); + TEST_JCC("s", 0, -1); + TEST_JCC("s", 0, 0); + + TEST_JCC("ns", 0, 1); + TEST_JCC("ns", 0, -1); + TEST_JCC("ns", 0, 0); +} + +#undef CC_MASK +#ifdef TEST_P4_FLAGS +#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A) +#else +#define CC_MASK (CC_O | CC_C) +#endif + +#define OP mul +#include "test-i386-muldiv.h" + +#define OP imul +#include "test-i386-muldiv.h" + +void test_imulw2(int op0, int op1) +{ + int res, s1, s0, flags; + s0 = op0; + s1 = op1; + res = s0; + flags = 0; + asm ("push %4\n\t" + "popf\n\t" + "imulw %w2, %w0\n\t" + "pushf\n\t" + "popl %1\n\t" + : "=q" (res), "=g" (flags) + : "q" (s1), "0" (res), "1" (flags)); + printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n", + "imulw", s0, s1, res, flags & CC_MASK); +} + +void test_imull2(int op0, int op1) +{ + int res, s1, s0, flags; + s0 = op0; + s1 = op1; + res = s0; + flags = 0; + asm ("push %4\n\t" + "popf\n\t" + "imull %2, %0\n\t" + "pushf\n\t" + "popl %1\n\t" + : "=q" (res), "=g" (flags) + : "q" (s1), "0" (res), "1" (flags)); + printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n", + "imull", s0, s1, res, flags & CC_MASK); +} + +#define TEST_IMUL_IM(size, size1, op0, op1)\ +{\ + int res, flags;\ + flags = 0;\ + res = 0;\ + asm ("push %3\n\t"\ + "popf\n\t"\ + "imul" size " $" #op0 ", %" size1 "2, %" size1 "0\n\t" \ + "pushf\n\t"\ + "popl %1\n\t"\ + : "=r" (res), "=g" (flags)\ + : "r" (op1), "1" (flags), "0" (res));\ + printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",\ + "imul" size, op0, op1, res, flags & CC_MASK);\ +} + + +#undef CC_MASK +#define CC_MASK (0) + +#define OP div +#include "test-i386-muldiv.h" + +#define OP idiv +#include "test-i386-muldiv.h" + +void test_mul(void) +{ + test_imulb(0x1234561d, 4); + test_imulb(3, -4); + test_imulb(0x80, 0x80); + test_imulb(0x10, 0x10); + + test_imulw(0, 0x1234001d, 45); + test_imulw(0, 23, -45); + test_imulw(0, 0x8000, 0x8000); + test_imulw(0, 0x100, 0x100); + + test_imull(0, 0x1234001d, 45); + test_imull(0, 23, -45); + test_imull(0, 0x80000000, 0x80000000); + test_imull(0, 0x10000, 0x10000); + + test_mulb(0x1234561d, 4); + test_mulb(3, -4); + test_mulb(0x80, 0x80); + test_mulb(0x10, 0x10); + + test_mulw(0, 0x1234001d, 45); + test_mulw(0, 23, -45); + test_mulw(0, 0x8000, 0x8000); + test_mulw(0, 0x100, 0x100); + + test_mull(0, 0x1234001d, 45); + test_mull(0, 23, -45); + test_mull(0, 0x80000000, 0x80000000); + test_mull(0, 0x10000, 0x10000); + + test_imulw2(0x1234001d, 45); + test_imulw2(23, -45); + test_imulw2(0x8000, 0x8000); + test_imulw2(0x100, 0x100); + + test_imull2(0x1234001d, 45); + test_imull2(23, -45); + test_imull2(0x80000000, 0x80000000); + test_imull2(0x10000, 0x10000); + + TEST_IMUL_IM("w", "w", 45, 0x1234); + TEST_IMUL_IM("w", "w", -45, 23); + TEST_IMUL_IM("w", "w", 0x8000, 0x80000000); + TEST_IMUL_IM("w", "w", 0x7fff, 0x1000); + + TEST_IMUL_IM("l", "", 45, 0x1234); + TEST_IMUL_IM("l", "", -45, 23); + TEST_IMUL_IM("l", "", 0x8000, 0x80000000); + TEST_IMUL_IM("l", "", 0x7fff, 0x1000); + + test_idivb(0x12341678, 0x127e); + test_idivb(0x43210123, -5); + test_idivb(0x12340004, -1); + + test_idivw(0, 0x12345678, 12347); + test_idivw(0, -23223, -45); + test_idivw(0, 0x12348000, -1); + test_idivw(0x12343, 0x12345678, 0x81238567); + + test_idivl(0, 0x12345678, 12347); + test_idivl(0, -233223, -45); + test_idivl(0, 0x80000000, -1); + test_idivl(0x12343, 0x12345678, 0x81234567); + + test_divb(0x12341678, 0x127e); + test_divb(0x43210123, -5); + test_divb(0x12340004, -1); + + test_divw(0, 0x12345678, 12347); + test_divw(0, -23223, -45); + test_divw(0, 0x12348000, -1); + test_divw(0x12343, 0x12345678, 0x81238567); + + test_divl(0, 0x12345678, 12347); + test_divl(0, -233223, -45); + test_divl(0, 0x80000000, -1); + test_divl(0x12343, 0x12345678, 0x81234567); +} + +#define TEST_BSX(op, size, op0)\ +{\ + int res, val, resz;\ + val = op0;\ + asm("xorl %1, %1\n"\ + "movl $0x12345678, %0\n"\ + #op " %" size "2, %" size "0 ; setz %b1" \ + : "=r" (res), "=q" (resz)\ + : "g" (val));\ + printf("%-10s A=%08x R=%08x %d\n", #op, val, res, resz);\ +} + +void test_bsx(void) +{ + TEST_BSX(bsrw, "w", 0); + TEST_BSX(bsrw, "w", 0x12340128); + TEST_BSX(bsrl, "", 0); + TEST_BSX(bsrl, "", 0x00340128); + TEST_BSX(bsfw, "w", 0); + TEST_BSX(bsfw, "w", 0x12340128); + TEST_BSX(bsfl, "", 0); + TEST_BSX(bsfl, "", 0x00340128); +} + +/**********************************************/ + +void test_fops(double a, double b) +{ + printf("a=%f b=%f a+b=%f\n", a, b, a + b); + printf("a=%f b=%f a-b=%f\n", a, b, a - b); + printf("a=%f b=%f a*b=%f\n", a, b, a * b); + printf("a=%f b=%f a/b=%f\n", a, b, a / b); + printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b)); + printf("a=%f sqrt(a)=%f\n", a, sqrt(a)); + printf("a=%f sin(a)=%f\n", a, sin(a)); + printf("a=%f cos(a)=%f\n", a, cos(a)); + printf("a=%f tan(a)=%f\n", a, tan(a)); + printf("a=%f log(a)=%f\n", a, log(a)); + printf("a=%f exp(a)=%f\n", a, exp(a)); + printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b)); + /* just to test some op combining */ + printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a))); + printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a))); + printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a))); + +} + +void test_fcmp(double a, double b) +{ + printf("(%f<%f)=%d\n", + a, b, a < b); + printf("(%f<=%f)=%d\n", + a, b, a <= b); + printf("(%f==%f)=%d\n", + a, b, a == b); + printf("(%f>%f)=%d\n", + a, b, a > b); + printf("(%f<=%f)=%d\n", + a, b, a >= b); + if (TEST_FCOMI) { + unsigned int eflags; + /* test f(u)comi instruction */ + asm("fcomi %2, %1\n" + "pushf\n" + "pop %0\n" + : "=r" (eflags) + : "t" (a), "u" (b)); + printf("fcomi(%f %f)=%08x\n", a, b, eflags & (CC_Z | CC_P | CC_C)); + } +} + +void test_fcvt(double a) +{ + float fa; + long double la; + int16_t fpuc; + int i; + int64_t lla; + int ia; + int16_t wa; + double ra; + + fa = a; + la = a; + printf("(float)%f = %f\n", a, fa); + printf("(long double)%f = %Lf\n", a, la); + printf("a=%016Lx\n", *(long long *)&a); + printf("la=%016Lx %04x\n", *(long long *)&la, + *(unsigned short *)((char *)(&la) + 8)); + + /* test all roundings */ + asm volatile ("fstcw %0" : "=m" (fpuc)); + for(i=0;i<4;i++) { + asm volatile ("fldcw %0" : : "m" ((fpuc & ~0x0c00) | (i << 10))); + asm volatile ("fist %0" : "=m" (wa) : "t" (a)); + asm volatile ("fistl %0" : "=m" (ia) : "t" (a)); + asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st"); + asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a)); + asm volatile ("fldcw %0" : : "m" (fpuc)); + printf("(short)a = %d\n", wa); + printf("(int)a = %d\n", ia); + printf("(int64_t)a = %Ld\n", lla); + printf("rint(a) = %f\n", ra); + } +} + +#define TEST(N) \ + asm("fld" #N : "=t" (a)); \ + printf("fld" #N "= %f\n", a); + +void test_fconst(void) +{ + double a; + TEST(1); + TEST(l2t); + TEST(l2e); + TEST(pi); + TEST(lg2); + TEST(ln2); + TEST(z); +} + +void test_fbcd(double a) +{ + unsigned short bcd[5]; + double b; + + asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st"); + asm("fbld %1" : "=t" (b) : "m" (bcd[0])); + printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n", + a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b); +} + +#define TEST_ENV(env, save, restore)\ +{\ + memset((env), 0xaa, sizeof(*(env)));\ + for(i=0;i<5;i++)\ + asm volatile ("fldl %0" : : "m" (dtab[i]));\ + asm(save " %0\n" : : "m" (*(env)));\ + asm(restore " %0\n": : "m" (*(env)));\ + for(i=0;i<5;i++)\ + asm volatile ("fstpl %0" : "=m" (rtab[i]));\ + for(i=0;i<5;i++)\ + printf("res[%d]=%f\n", i, rtab[i]);\ + printf("fpuc=%04x fpus=%04x fptag=%04x\n",\ + (env)->fpuc,\ + (env)->fpus & 0xff00,\ + (env)->fptag);\ +} + +void test_fenv(void) +{ + struct __attribute__((packed)) { + uint16_t fpuc; + uint16_t dummy1; + uint16_t fpus; + uint16_t dummy2; + uint16_t fptag; + uint16_t dummy3; + uint32_t ignored[4]; + long double fpregs[8]; + } float_env32; + struct __attribute__((packed)) { + uint16_t fpuc; + uint16_t fpus; + uint16_t fptag; + uint16_t ignored[4]; + long double fpregs[8]; + } float_env16; + double dtab[8]; + double rtab[8]; + int i; + + for(i=0;i<8;i++) + dtab[i] = i + 1; + + TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv"); + TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor"); + TEST_ENV(&float_env32, "fnstenv", "fldenv"); + TEST_ENV(&float_env32, "fnsave", "frstor"); + + /* test for ffree */ + for(i=0;i<5;i++) + asm volatile ("fldl %0" : : "m" (dtab[i])); + asm volatile("ffree %st(2)"); + asm volatile ("fnstenv %0\n" : : "m" (float_env32)); + asm volatile ("fninit"); + printf("fptag=%04x\n", float_env32.fptag); +} + + +#define TEST_FCMOV(a, b, eflags, CC)\ +{\ + double res;\ + asm("push %3\n"\ + "popf\n"\ + "fcmov" CC " %2, %0\n"\ + : "=t" (res)\ + : "0" (a), "u" (b), "g" (eflags));\ + printf("fcmov%s eflags=0x%04x-> %f\n", \ + CC, eflags, res);\ +} + +void test_fcmov(void) +{ + double a, b; + int eflags, i; + + a = 1.0; + b = 2.0; + for(i = 0; i < 4; i++) { + eflags = 0; + if (i & 1) + eflags |= CC_C; + if (i & 2) + eflags |= CC_Z; + TEST_FCMOV(a, b, eflags, "b"); + TEST_FCMOV(a, b, eflags, "e"); + TEST_FCMOV(a, b, eflags, "be"); + TEST_FCMOV(a, b, eflags, "nb"); + TEST_FCMOV(a, b, eflags, "ne"); + TEST_FCMOV(a, b, eflags, "nbe"); + } + TEST_FCMOV(a, b, 0, "u"); + TEST_FCMOV(a, b, CC_P, "u"); + TEST_FCMOV(a, b, 0, "nu"); + TEST_FCMOV(a, b, CC_P, "nu"); +} + +void test_floats(void) +{ + test_fops(2, 3); + test_fops(1.4, -5); + test_fcmp(2, -1); + test_fcmp(2, 2); + test_fcmp(2, 3); + test_fcvt(0.5); + test_fcvt(-0.5); + test_fcvt(1.0/7.0); + test_fcvt(-1.0/9.0); + test_fcvt(32768); + test_fcvt(-1e20); + test_fconst(); + test_fbcd(1234567890123456); + test_fbcd(-123451234567890); + test_fenv(); + if (TEST_CMOV) { + test_fcmov(); + } +} + +/**********************************************/ + +#define TEST_BCD(op, op0, cc_in, cc_mask)\ +{\ + int res, flags;\ + res = op0;\ + flags = cc_in;\ + asm ("push %3\n\t"\ + "popf\n\t"\ + #op "\n\t"\ + "pushf\n\t"\ + "popl %1\n\t"\ + : "=a" (res), "=g" (flags)\ + : "0" (res), "1" (flags));\ + printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\ + #op, op0, res, cc_in, flags & cc_mask);\ +} + +void test_bcd(void) +{ + TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + + TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A)); + + TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A)); + TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A)); + TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A)); + TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A)); + TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A)); + TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A)); + TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A)); + TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A)); + + TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A)); + TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A)); + TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A)); + TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A)); + TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A)); + TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A)); + TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A)); + TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A)); + + TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)); + TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)); +} + +#define TEST_XCHG(op, size, opconst)\ +{\ + int op0, op1;\ + op0 = 0x12345678;\ + op1 = 0xfbca7654;\ + asm(#op " %" size "0, %" size "1" \ + : "=q" (op0), opconst (op1) \ + : "0" (op0), "1" (op1));\ + printf("%-10s A=%08x B=%08x\n",\ + #op, op0, op1);\ +} + +#define TEST_CMPXCHG(op, size, opconst, eax)\ +{\ + int op0, op1;\ + op0 = 0x12345678;\ + op1 = 0xfbca7654;\ + asm(#op " %" size "0, %" size "1" \ + : "=q" (op0), opconst (op1) \ + : "0" (op0), "1" (op1), "a" (eax));\ + printf("%-10s EAX=%08x A=%08x C=%08x\n",\ + #op, eax, op0, op1);\ +} + +void test_xchg(void) +{ + TEST_XCHG(xchgl, "", "=q"); + TEST_XCHG(xchgw, "w", "=q"); + TEST_XCHG(xchgb, "b", "=q"); + + TEST_XCHG(xchgl, "", "=m"); + TEST_XCHG(xchgw, "w", "=m"); + TEST_XCHG(xchgb, "b", "=m"); + + TEST_XCHG(xaddl, "", "=q"); + TEST_XCHG(xaddw, "w", "=q"); + TEST_XCHG(xaddb, "b", "=q"); + + { + int res; + res = 0x12345678; + asm("xaddl %1, %0" : "=r" (res) : "0" (res)); + printf("xaddl same res=%08x\n", res); + } + + TEST_XCHG(xaddl, "", "=m"); + TEST_XCHG(xaddw, "w", "=m"); + TEST_XCHG(xaddb, "b", "=m"); + + TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfbca7654); + TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfbca7654); + TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfbca7654); + + TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfffefdfc); + TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfffefdfc); + TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfffefdfc); + + TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfbca7654); + TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfbca7654); + TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfbca7654); + + TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfffefdfc); + TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfffefdfc); + TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfffefdfc); + + { + uint64_t op0, op1, op2; + int i, eflags; + + for(i = 0; i < 2; i++) { + op0 = 0x123456789abcd; + if (i == 0) + op1 = 0xfbca765423456; + else + op1 = op0; + op2 = 0x6532432432434; + asm("cmpxchg8b %1\n" + "pushf\n" + "popl %2\n" + : "=A" (op0), "=m" (op1), "=g" (eflags) + : "0" (op0), "m" (op1), "b" ((int)op2), "c" ((int)(op2 >> 32))); + printf("cmpxchg8b: op0=%016llx op1=%016llx CC=%02x\n", + op0, op1, eflags & CC_Z); + } + } +} + +/**********************************************/ +/* segmentation tests */ + +#include +#include +#include + +_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66) +#define modify_ldt_ldt_s user_desc +#endif + +uint8_t seg_data1[4096]; +uint8_t seg_data2[4096]; + +#define MK_SEL(n) (((n) << 3) | 7) + +#define TEST_LR(op, size, seg, mask)\ +{\ + int res, res2;\ + res = 0x12345678;\ + asm (op " %" size "2, %" size "0\n" \ + "movl $0, %1\n"\ + "jnz 1f\n"\ + "movl $1, %1\n"\ + "1:\n"\ + : "=r" (res), "=r" (res2) : "m" (seg), "0" (res));\ + printf(op ": Z=%d %08x\n", res2, res & ~(mask));\ +} + +/* NOTE: we use Linux modify_ldt syscall */ +void test_segs(void) +{ + struct modify_ldt_ldt_s ldt; + long long ldt_table[3]; + int res, res2; + char tmp; + struct { + uint32_t offset; + uint16_t seg; + } __attribute__((packed)) segoff; + + ldt.entry_number = 1; + ldt.base_addr = (unsigned long)&seg_data1; + ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12; + ldt.seg_32bit = 1; + ldt.contents = MODIFY_LDT_CONTENTS_DATA; + ldt.read_exec_only = 0; + ldt.limit_in_pages = 1; + ldt.seg_not_present = 0; + ldt.useable = 1; + modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ + + ldt.entry_number = 2; + ldt.base_addr = (unsigned long)&seg_data2; + ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12; + ldt.seg_32bit = 1; + ldt.contents = MODIFY_LDT_CONTENTS_DATA; + ldt.read_exec_only = 0; + ldt.limit_in_pages = 1; + ldt.seg_not_present = 0; + ldt.useable = 1; + modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ + + modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */ +#if 0 + { + int i; + for(i=0;i<3;i++) + printf("%d: %016Lx\n", i, ldt_table[i]); + } +#endif + /* do some tests with fs or gs */ + asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1))); + + seg_data1[1] = 0xaa; + seg_data2[1] = 0x55; + + asm volatile ("fs movzbl 0x1, %0" : "=r" (res)); + printf("FS[1] = %02x\n", res); + + asm volatile ("pushl %%gs\n" + "movl %1, %%gs\n" + "gs movzbl 0x1, %0\n" + "popl %%gs\n" + : "=r" (res) + : "r" (MK_SEL(2))); + printf("GS[1] = %02x\n", res); + + /* tests with ds/ss (implicit segment case) */ + tmp = 0xa5; + asm volatile ("pushl %%ebp\n\t" + "pushl %%ds\n\t" + "movl %2, %%ds\n\t" + "movl %3, %%ebp\n\t" + "movzbl 0x1, %0\n\t" + "movzbl (%%ebp), %1\n\t" + "popl %%ds\n\t" + "popl %%ebp\n\t" + : "=r" (res), "=r" (res2) + : "r" (MK_SEL(1)), "r" (&tmp)); + printf("DS[1] = %02x\n", res); + printf("SS[tmp] = %02x\n", res2); + + segoff.seg = MK_SEL(2); + segoff.offset = 0xabcdef12; + asm volatile("lfs %2, %0\n\t" + "movl %%fs, %1\n\t" + : "=r" (res), "=g" (res2) + : "m" (segoff)); + printf("FS:reg = %04x:%08x\n", res2, res); + + TEST_LR("larw", "w", MK_SEL(2), 0x0100); + TEST_LR("larl", "", MK_SEL(2), 0x0100); + TEST_LR("lslw", "w", MK_SEL(2), 0); + TEST_LR("lsll", "", MK_SEL(2), 0); + + TEST_LR("larw", "w", 0xfff8, 0); + TEST_LR("larl", "", 0xfff8, 0); + TEST_LR("lslw", "w", 0xfff8, 0); + TEST_LR("lsll", "", 0xfff8, 0); +} + +/* 16 bit code test */ +extern char code16_start, code16_end; +extern char code16_func1; +extern char code16_func2; +extern char code16_func3; + +void test_code16(void) +{ + struct modify_ldt_ldt_s ldt; + int res, res2; + + /* build a code segment */ + ldt.entry_number = 1; + ldt.base_addr = (unsigned long)&code16_start; + ldt.limit = &code16_end - &code16_start; + ldt.seg_32bit = 0; + ldt.contents = MODIFY_LDT_CONTENTS_CODE; + ldt.read_exec_only = 0; + ldt.limit_in_pages = 0; + ldt.seg_not_present = 0; + ldt.useable = 1; + modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ + + /* call the first function */ + asm volatile ("lcall %1, %2" + : "=a" (res) + : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc"); + printf("func1() = 0x%08x\n", res); + asm volatile ("lcall %2, %3" + : "=a" (res), "=c" (res2) + : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc"); + printf("func2() = 0x%08x spdec=%d\n", res, res2); + asm volatile ("lcall %1, %2" + : "=a" (res) + : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc"); + printf("func3() = 0x%08x\n", res); +} + +extern char func_lret32; +extern char func_iret32; + +void test_misc(void) +{ + char table[256]; + int res, i; + + for(i=0;i<256;i++) table[i] = 256 - i; + res = 0x12345678; + asm ("xlat" : "=a" (res) : "b" (table), "0" (res)); + printf("xlat: EAX=%08x\n", res); + + asm volatile ("pushl %%cs ; call %1" + : "=a" (res) + : "m" (func_lret32): "memory", "cc"); + printf("func_lret32=%x\n", res); + + asm volatile ("pushfl ; pushl %%cs ; call %1" + : "=a" (res) + : "m" (func_iret32): "memory", "cc"); + printf("func_iret32=%x\n", res); + + /* specific popl test */ + asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popl (%%esp) ; popl %0" + : "=g" (res)); + printf("popl esp=%x\n", res); + + /* specific popw test */ + asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popw (%%esp) ; addl $2, %%esp ; popl %0" + : "=g" (res)); + printf("popw esp=%x\n", res); +} + +uint8_t str_buffer[4096]; + +#define TEST_STRING1(OP, size, DF, REP)\ +{\ + int esi, edi, eax, ecx, eflags;\ +\ + esi = (long)(str_buffer + sizeof(str_buffer) / 2);\ + edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\ + eax = 0x12345678;\ + ecx = 17;\ +\ + asm volatile ("pushl $0\n\t"\ + "popf\n\t"\ + DF "\n\t"\ + REP #OP size "\n\t"\ + "cld\n\t"\ + "pushf\n\t"\ + "popl %4\n\t"\ + : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\ + : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\ + printf("%-10s ESI=%08x EDI=%08x EAX=%08x ECX=%08x EFL=%04x\n",\ + REP #OP size, esi, edi, eax, ecx,\ + eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\ +} + +#define TEST_STRING(OP, REP)\ + TEST_STRING1(OP, "b", "", REP);\ + TEST_STRING1(OP, "w", "", REP);\ + TEST_STRING1(OP, "l", "", REP);\ + TEST_STRING1(OP, "b", "std", REP);\ + TEST_STRING1(OP, "w", "std", REP);\ + TEST_STRING1(OP, "l", "std", REP) + +void test_string(void) +{ + int i; + for(i = 0;i < sizeof(str_buffer); i++) + str_buffer[i] = i + 0x56; + TEST_STRING(stos, ""); + TEST_STRING(stos, "rep "); + TEST_STRING(lods, ""); /* to verify stos */ + TEST_STRING(lods, "rep "); + TEST_STRING(movs, ""); + TEST_STRING(movs, "rep "); + TEST_STRING(lods, ""); /* to verify stos */ + + /* XXX: better tests */ + TEST_STRING(scas, ""); + TEST_STRING(scas, "repz "); + TEST_STRING(scas, "repnz "); + TEST_STRING(cmps, ""); + TEST_STRING(cmps, "repz "); + TEST_STRING(cmps, "repnz "); +} + +/* VM86 test */ + +static inline void set_bit(uint8_t *a, unsigned int bit) +{ + a[bit / 8] |= (1 << (bit % 8)); +} + +static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg) +{ + return (uint8_t *)((seg << 4) + (reg & 0xffff)); +} + +static inline void pushw(struct vm86_regs *r, int val) +{ + r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff); + *(uint16_t *)seg_to_linear(r->ss, r->esp) = val; +} + +#undef __syscall_return +#define __syscall_return(type, res) \ +do { \ + return (type) (res); \ +} while (0) + +_syscall2(int, vm86, int, func, struct vm86plus_struct *, v86) + +extern char vm86_code_start; +extern char vm86_code_end; + +#define VM86_CODE_CS 0x100 +#define VM86_CODE_IP 0x100 + +void test_vm86(void) +{ + struct vm86plus_struct ctx; + struct vm86_regs *r; + uint8_t *vm86_mem; + int seg, ret; + + vm86_mem = mmap((void *)0x00000000, 0x110000, + PROT_WRITE | PROT_READ | PROT_EXEC, + MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); + if (vm86_mem == MAP_FAILED) { + printf("ERROR: could not map vm86 memory"); + return; + } + memset(&ctx, 0, sizeof(ctx)); + + /* init basic registers */ + r = &ctx.regs; + r->eip = VM86_CODE_IP; + r->esp = 0xfffe; + seg = VM86_CODE_CS; + r->cs = seg; + r->ss = seg; + r->ds = seg; + r->es = seg; + r->fs = seg; + r->gs = seg; + r->eflags = VIF_MASK; + + /* move code to proper address. We use the same layout as a .com + dos program. */ + memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP, + &vm86_code_start, &vm86_code_end - &vm86_code_start); + + /* mark int 0x21 as being emulated */ + set_bit((uint8_t *)&ctx.int_revectored, 0x21); + + for(;;) { + ret = vm86(VM86_ENTER, &ctx); + switch(VM86_TYPE(ret)) { + case VM86_INTx: + { + int int_num, ah, v; + + int_num = VM86_ARG(ret); + if (int_num != 0x21) + goto unknown_int; + ah = (r->eax >> 8) & 0xff; + switch(ah) { + case 0x00: /* exit */ + goto the_end; + case 0x02: /* write char */ + { + uint8_t c = r->edx; + putchar(c); + } + break; + case 0x09: /* write string */ + { + uint8_t c, *ptr; + ptr = seg_to_linear(r->ds, r->edx); + for(;;) { + c = *ptr++; + if (c == '$') + break; + putchar(c); + } + r->eax = (r->eax & ~0xff) | '$'; + } + break; + case 0xff: /* extension: write eflags number in edx */ + v = (int)r->edx; +#ifndef LINUX_VM86_IOPL_FIX + v &= ~0x3000; +#endif + printf("%08x\n", v); + break; + default: + unknown_int: + printf("unsupported int 0x%02x\n", int_num); + goto the_end; + } + } + break; + case VM86_SIGNAL: + /* a signal came, we just ignore that */ + break; + case VM86_STI: + break; + default: + printf("ERROR: unhandled vm86 return code (0x%x)\n", ret); + goto the_end; + } + } + the_end: + printf("VM86 end\n"); + munmap(vm86_mem, 0x110000); +} + +/* exception tests */ +#ifndef REG_EAX +#define REG_EAX EAX +#define REG_EBX EBX +#define REG_ECX ECX +#define REG_EDX EDX +#define REG_ESI ESI +#define REG_EDI EDI +#define REG_EBP EBP +#define REG_ESP ESP +#define REG_EIP EIP +#define REG_EFL EFL +#define REG_TRAPNO TRAPNO +#define REG_ERR ERR +#endif + +jmp_buf jmp_env; +int v1; +int tab[2]; + +void sig_handler(int sig, siginfo_t *info, void *puc) +{ + struct ucontext *uc = puc; + + printf("si_signo=%d si_errno=%d si_code=%d", + info->si_signo, info->si_errno, info->si_code); + printf(" si_addr=0x%08lx", + (unsigned long)info->si_addr); + printf("\n"); + + printf("trapno=0x%02x err=0x%08x", + uc->uc_mcontext.gregs[REG_TRAPNO], + uc->uc_mcontext.gregs[REG_ERR]); + printf(" EIP=0x%08x", uc->uc_mcontext.gregs[REG_EIP]); + printf("\n"); + longjmp(jmp_env, 1); +} + +void test_exceptions(void) +{ + struct modify_ldt_ldt_s ldt; + struct sigaction act; + volatile int val; + + act.sa_sigaction = sig_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_SIGINFO; + sigaction(SIGFPE, &act, NULL); + sigaction(SIGILL, &act, NULL); + sigaction(SIGSEGV, &act, NULL); + sigaction(SIGBUS, &act, NULL); + sigaction(SIGTRAP, &act, NULL); + + /* test division by zero reporting */ + printf("DIVZ exception:\n"); + if (setjmp(jmp_env) == 0) { + /* now divide by zero */ + v1 = 0; + v1 = 2 / v1; + } + + printf("BOUND exception:\n"); + if (setjmp(jmp_env) == 0) { + /* bound exception */ + tab[0] = 1; + tab[1] = 10; + asm volatile ("bound %0, %1" : : "r" (11), "m" (tab[0])); + } + + printf("segment exceptions:\n"); + if (setjmp(jmp_env) == 0) { + /* load an invalid segment */ + asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1)); + } + if (setjmp(jmp_env) == 0) { + /* null data segment is valid */ + asm volatile ("movl %0, %%fs" : : "r" (3)); + /* null stack segment */ + asm volatile ("movl %0, %%ss" : : "r" (3)); + } + + ldt.entry_number = 1; + ldt.base_addr = (unsigned long)&seg_data1; + ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12; + ldt.seg_32bit = 1; + ldt.contents = MODIFY_LDT_CONTENTS_DATA; + ldt.read_exec_only = 0; + ldt.limit_in_pages = 1; + ldt.seg_not_present = 1; + ldt.useable = 1; + modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */ + + if (setjmp(jmp_env) == 0) { + /* segment not present */ + asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1))); + } + + /* test SEGV reporting */ + printf("PF exception:\n"); + if (setjmp(jmp_env) == 0) { + val = 1; + /* we add a nop to test a weird PC retrieval case */ + asm volatile ("nop"); + /* now store in an invalid address */ + *(char *)0x1234 = 1; + } + + /* test SEGV reporting */ + printf("PF exception:\n"); + if (setjmp(jmp_env) == 0) { + val = 1; + /* read from an invalid address */ + v1 = *(char *)0x1234; + } + + /* test illegal instruction reporting */ + printf("UD2 exception:\n"); + if (setjmp(jmp_env) == 0) { + /* now execute an invalid instruction */ + asm volatile("ud2"); + } + printf("lock nop exception:\n"); + if (setjmp(jmp_env) == 0) { + /* now execute an invalid instruction */ + asm volatile("lock nop"); + } + + printf("INT exception:\n"); + if (setjmp(jmp_env) == 0) { + asm volatile ("int $0xfd"); + } + if (setjmp(jmp_env) == 0) { + asm volatile ("int $0x01"); + } + if (setjmp(jmp_env) == 0) { + asm volatile (".byte 0xcd, 0x03"); + } + if (setjmp(jmp_env) == 0) { + asm volatile ("int $0x04"); + } + if (setjmp(jmp_env) == 0) { + asm volatile ("int $0x05"); + } + + printf("INT3 exception:\n"); + if (setjmp(jmp_env) == 0) { + asm volatile ("int3"); + } + + printf("CLI exception:\n"); + if (setjmp(jmp_env) == 0) { + asm volatile ("cli"); + } + + printf("STI exception:\n"); + if (setjmp(jmp_env) == 0) { + asm volatile ("cli"); + } + + printf("INTO exception:\n"); + if (setjmp(jmp_env) == 0) { + /* overflow exception */ + asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff)); + } + + printf("OUTB exception:\n"); + if (setjmp(jmp_env) == 0) { + asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0)); + } + + printf("INB exception:\n"); + if (setjmp(jmp_env) == 0) { + asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321)); + } + + printf("REP OUTSB exception:\n"); + if (setjmp(jmp_env) == 0) { + asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1)); + } + + printf("REP INSB exception:\n"); + if (setjmp(jmp_env) == 0) { + asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1)); + } + + printf("HLT exception:\n"); + if (setjmp(jmp_env) == 0) { + asm volatile ("hlt"); + } + + printf("single step exception:\n"); + val = 0; + if (setjmp(jmp_env) == 0) { + asm volatile ("pushf\n" + "orl $0x00100, (%%esp)\n" + "popf\n" + "movl $0xabcd, %0\n" + "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory"); + } + printf("val=0x%x\n", val); +} + +/* specific precise single step test */ +void sig_trap_handler(int sig, siginfo_t *info, void *puc) +{ + struct ucontext *uc = puc; + printf("EIP=0x%08x\n", uc->uc_mcontext.gregs[REG_EIP]); +} + +const uint8_t sstep_buf1[4] = { 1, 2, 3, 4}; +uint8_t sstep_buf2[4]; + +void test_single_step(void) +{ + struct sigaction act; + volatile int val; + int i; + + val = 0; + act.sa_sigaction = sig_trap_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_SIGINFO; + sigaction(SIGTRAP, &act, NULL); + asm volatile ("pushf\n" + "orl $0x00100, (%%esp)\n" + "popf\n" + "movl $0xabcd, %0\n" + + /* jmp test */ + "movl $3, %%ecx\n" + "1:\n" + "addl $1, %0\n" + "decl %%ecx\n" + "jnz 1b\n" + + /* movsb: the single step should stop at each movsb iteration */ + "movl $sstep_buf1, %%esi\n" + "movl $sstep_buf2, %%edi\n" + "movl $0, %%ecx\n" + "rep movsb\n" + "movl $3, %%ecx\n" + "rep movsb\n" + "movl $1, %%ecx\n" + "rep movsb\n" + + /* cmpsb: the single step should stop at each cmpsb iteration */ + "movl $sstep_buf1, %%esi\n" + "movl $sstep_buf2, %%edi\n" + "movl $0, %%ecx\n" + "rep cmpsb\n" + "movl $4, %%ecx\n" + "rep cmpsb\n" + + /* getpid() syscall: single step should skip one + instruction */ + "movl $20, %%eax\n" + "int $0x80\n" + "movl $0, %%eax\n" + + /* when modifying SS, trace is not done on the next + instruction */ + "movl %%ss, %%ecx\n" + "movl %%ecx, %%ss\n" + "addl $1, %0\n" + "movl $1, %%eax\n" + "movl %%ecx, %%ss\n" + "jmp 1f\n" + "addl $1, %0\n" + "1:\n" + "movl $1, %%eax\n" + "pushl %%ecx\n" + "popl %%ss\n" + "addl $1, %0\n" + "movl $1, %%eax\n" + + "pushf\n" + "andl $~0x00100, (%%esp)\n" + "popf\n" + : "=m" (val) + : + : "cc", "memory", "eax", "ecx", "esi", "edi"); + printf("val=%d\n", val); + for(i = 0; i < 4; i++) + printf("sstep_buf2[%d] = %d\n", i, sstep_buf2[i]); +} + +/* self modifying code test */ +uint8_t code[] = { + 0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */ + 0xc3, /* ret */ +}; + +asm("smc_code2:\n" + "movl 4(%esp), %eax\n" + "movl %eax, smc_patch_addr2 + 1\n" + "nop\n" + "nop\n" + "nop\n" + "nop\n" + "nop\n" + "nop\n" + "nop\n" + "nop\n" + "smc_patch_addr2:\n" + "movl $1, %eax\n" + "ret\n"); + +typedef int FuncType(void); +extern int smc_code2(int); +void test_self_modifying_code(void) +{ + int i; + + printf("self modifying code:\n"); + printf("func1 = 0x%x\n", ((FuncType *)code)()); + for(i = 2; i <= 4; i++) { + code[1] = i; + printf("func%d = 0x%x\n", i, ((FuncType *)code)()); + } + + /* more difficult test : the modified code is just after the + modifying instruction. It is forbidden in Intel specs, but it + is used by old DOS programs */ + for(i = 2; i <= 4; i++) { + printf("smc_code2(%d) = %d\n", i, smc_code2(i)); + } +} + +int enter_stack[4096]; + +#define TEST_ENTER(size, stack_type, level)\ +{\ + int esp_save, esp_val, ebp_val, ebp_save, i;\ + stack_type *ptr, *stack_end, *stack_ptr;\ + memset(enter_stack, 0, sizeof(enter_stack));\ + stack_end = stack_ptr = (stack_type *)(enter_stack + 4096);\ + ebp_val = (long)stack_ptr;\ + for(i=1;i<=32;i++)\ + *--stack_ptr = i;\ + esp_val = (long)stack_ptr;\ + asm("movl %%esp, %[esp_save]\n"\ + "movl %%ebp, %[ebp_save]\n"\ + "movl %[esp_val], %%esp\n"\ + "movl %[ebp_val], %%ebp\n"\ + "enter" size " $12, $" #level "\n"\ + "movl %%esp, %[esp_val]\n"\ + "movl %%ebp, %[ebp_val]\n"\ + "movl %[esp_save], %%esp\n"\ + "movl %[ebp_save], %%ebp\n"\ + : [esp_save] "=r" (esp_save),\ + [ebp_save] "=r" (ebp_save),\ + [esp_val] "=r" (esp_val),\ + [ebp_val] "=r" (ebp_val)\ + : "[esp_val]" (esp_val),\ + "[ebp_val]" (ebp_val));\ + printf("level=%d:\n", level);\ + printf("esp_val=0x%08lx\n", esp_val - (long)stack_end);\ + printf("ebp_val=0x%08lx\n", ebp_val - (long)stack_end);\ + for(ptr = (stack_type *)esp_val; ptr < stack_end; ptr++)\ + printf("%08x\n", ptr[0]);\ +} + +static void test_enter(void) +{ + TEST_ENTER("l", uint32_t, 0); + TEST_ENTER("l", uint32_t, 1); + TEST_ENTER("l", uint32_t, 2); + TEST_ENTER("l", uint32_t, 31); + + TEST_ENTER("w", uint16_t, 0); + TEST_ENTER("w", uint16_t, 1); + TEST_ENTER("w", uint16_t, 2); + TEST_ENTER("w", uint16_t, 31); +} + + +static void *call_end __init_call = NULL; + +int main(int argc, char **argv) +{ + void **ptr; + void (*func)(void); + + ptr = &call_start + 1; + while (*ptr != NULL) { + func = *ptr++; + func(); + } + test_bsx(); + test_mul(); + test_jcc(); + test_floats(); + test_bcd(); + test_xchg(); + test_string(); + test_misc(); + test_lea(); + test_segs(); + test_code16(); + test_vm86(); + test_exceptions(); + test_self_modifying_code(); + test_single_step(); + test_enter(); + return 0; +} diff --git a/tools/ioemu/tests/test-i386.h b/tools/ioemu/tests/test-i386.h new file mode 100644 index 0000000000..7d1812c883 --- /dev/null +++ b/tools/ioemu/tests/test-i386.h @@ -0,0 +1,131 @@ + +#define exec_op glue(exec_, OP) +#define exec_opl glue(glue(exec_, OP), l) +#define exec_opw glue(glue(exec_, OP), w) +#define exec_opb glue(glue(exec_, OP), b) + +#define EXECOP2(size, res, s1, flags) \ + asm ("push %4\n\t"\ + "popf\n\t"\ + stringify(OP) size " %" size "2, %" size "0\n\t" \ + "pushf\n\t"\ + "popl %1\n\t"\ + : "=q" (res), "=g" (flags)\ + : "q" (s1), "0" (res), "1" (flags)); + +#define EXECOP1(size, res, flags) \ + asm ("push %3\n\t"\ + "popf\n\t"\ + stringify(OP) size " %" size "0\n\t" \ + "pushf\n\t"\ + "popl %1\n\t"\ + : "=q" (res), "=g" (flags)\ + : "0" (res), "1" (flags)); + +#ifdef OP1 +void exec_opl(int s0, int s1, int iflags) +{ + int res, flags; + res = s0; + flags = iflags; + EXECOP1("", res, flags); + printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n", + stringify(OP) "l", s0, res, iflags, flags & CC_MASK); +} + +void exec_opw(int s0, int s1, int iflags) +{ + int res, flags; + res = s0; + flags = iflags; + EXECOP1("w", res, flags); + printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n", + stringify(OP) "w", s0, res, iflags, flags & CC_MASK); +} + +void exec_opb(int s0, int s1, int iflags) +{ + int res, flags; + res = s0; + flags = iflags; + EXECOP1("b", res, flags); + printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n", + stringify(OP) "b", s0, res, iflags, flags & CC_MASK); +} +#else +void exec_opl(int s0, int s1, int iflags) +{ + int res, flags; + res = s0; + flags = iflags; + EXECOP2("", res, s1, flags); + printf("%-10s A=%08x B=%08x R=%08x CCIN=%04x CC=%04x\n", + stringify(OP) "l", s0, s1, res, iflags, flags & CC_MASK); +} + +void exec_opw(int s0, int s1, int iflags) +{ + int res, flags; + res = s0; + flags = iflags; + EXECOP2("w", res, s1, flags); + printf("%-10s A=%08x B=%08x R=%08x CCIN=%04x CC=%04x\n", + stringify(OP) "w", s0, s1, res, iflags, flags & CC_MASK); +} + +void exec_opb(int s0, int s1, int iflags) +{ + int res, flags; + res = s0; + flags = iflags; + EXECOP2("b", res, s1, flags); + printf("%-10s A=%08x B=%08x R=%08x CCIN=%04x CC=%04x\n", + stringify(OP) "b", s0, s1, res, iflags, flags & CC_MASK); +} +#endif + +void exec_op(int s0, int s1) +{ + exec_opl(s0, s1, 0); + exec_opw(s0, s1, 0); + exec_opb(s0, s1, 0); +#ifdef OP_CC + exec_opl(s0, s1, CC_C); + exec_opw(s0, s1, CC_C); + exec_opb(s0, s1, CC_C); +#endif +} + +void glue(test_, OP)(void) +{ + exec_op(0x12345678, 0x812FADA); + exec_op(0x12341, 0x12341); + exec_op(0x12341, -0x12341); + exec_op(0xffffffff, 0); + exec_op(0xffffffff, -1); + exec_op(0xffffffff, 1); + exec_op(0xffffffff, 2); + exec_op(0x7fffffff, 0); + exec_op(0x7fffffff, 1); + exec_op(0x7fffffff, -1); + exec_op(0x80000000, -1); + exec_op(0x80000000, 1); + exec_op(0x80000000, -2); + exec_op(0x12347fff, 0); + exec_op(0x12347fff, 1); + exec_op(0x12347fff, -1); + exec_op(0x12348000, -1); + exec_op(0x12348000, 1); + exec_op(0x12348000, -2); + exec_op(0x12347f7f, 0); + exec_op(0x12347f7f, 1); + exec_op(0x12347f7f, -1); + exec_op(0x12348080, -1); + exec_op(0x12348080, 1); + exec_op(0x12348080, -2); +} + +void *glue(_test_, OP) __init_call = glue(test_, OP); + +#undef OP +#undef OP_CC diff --git a/tools/ioemu/tests/test_path.c b/tools/ioemu/tests/test_path.c new file mode 100644 index 0000000000..a9b52de378 --- /dev/null +++ b/tools/ioemu/tests/test_path.c @@ -0,0 +1,152 @@ +/* Test path override code */ +#define _GNU_SOURCE +#include "../path.c" +#include +#include +#include + +/* Any log message kills the test. */ +void gemu_log(const char *fmt, ...) +{ + va_list ap; + + fprintf(stderr, "FATAL: "); + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(1); +} + +#define NO_CHANGE(_path) \ + do { \ + if (strcmp(path(_path), _path) != 0) return __LINE__; \ + } while(0) + +#define CHANGE_TO(_path, _newpath) \ + do { \ + if (strcmp(path(_path), _newpath) != 0) return __LINE__; \ + } while(0) + +static void cleanup(void) +{ + unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE"); + unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE2"); + unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE3"); + unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE4"); + unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE5"); + rmdir("/tmp/qemu-test_path/DIR1/DIR2"); + rmdir("/tmp/qemu-test_path/DIR1/DIR3"); + rmdir("/tmp/qemu-test_path/DIR1"); + rmdir("/tmp/qemu-test_path"); +} + +static unsigned int do_test(void) +{ + if (mkdir("/tmp/qemu-test_path", 0700) != 0) + return __LINE__; + + if (mkdir("/tmp/qemu-test_path/DIR1", 0700) != 0) + return __LINE__; + + if (mkdir("/tmp/qemu-test_path/DIR1/DIR2", 0700) != 0) + return __LINE__; + + if (mkdir("/tmp/qemu-test_path/DIR1/DIR3", 0700) != 0) + return __LINE__; + + if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE", 0600)) != 0) + return __LINE__; + + if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE2", 0600)) != 0) + return __LINE__; + + if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE3", 0600)) != 0) + return __LINE__; + + if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE4", 0600)) != 0) + return __LINE__; + + if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE5", 0600)) != 0) + return __LINE__; + + init_paths("/tmp/qemu-test_path"); + + NO_CHANGE("/tmp"); + NO_CHANGE("/tmp/"); + NO_CHANGE("/tmp/qemu-test_path"); + NO_CHANGE("/tmp/qemu-test_path/"); + NO_CHANGE("/tmp/qemu-test_path/D"); + NO_CHANGE("/tmp/qemu-test_path/DI"); + NO_CHANGE("/tmp/qemu-test_path/DIR"); + NO_CHANGE("/tmp/qemu-test_path/DIR1"); + NO_CHANGE("/tmp/qemu-test_path/DIR1/"); + + NO_CHANGE("/D"); + NO_CHANGE("/DI"); + NO_CHANGE("/DIR"); + NO_CHANGE("/DIR2"); + NO_CHANGE("/DIR1."); + + CHANGE_TO("/DIR1", "/tmp/qemu-test_path/DIR1"); + CHANGE_TO("/DIR1/", "/tmp/qemu-test_path/DIR1"); + + NO_CHANGE("/DIR1/D"); + NO_CHANGE("/DIR1/DI"); + NO_CHANGE("/DIR1/DIR"); + NO_CHANGE("/DIR1/DIR1"); + + CHANGE_TO("/DIR1/DIR2", "/tmp/qemu-test_path/DIR1/DIR2"); + CHANGE_TO("/DIR1/DIR2/", "/tmp/qemu-test_path/DIR1/DIR2"); + + CHANGE_TO("/DIR1/DIR3", "/tmp/qemu-test_path/DIR1/DIR3"); + CHANGE_TO("/DIR1/DIR3/", "/tmp/qemu-test_path/DIR1/DIR3"); + + NO_CHANGE("/DIR1/DIR2/F"); + NO_CHANGE("/DIR1/DIR2/FI"); + NO_CHANGE("/DIR1/DIR2/FIL"); + NO_CHANGE("/DIR1/DIR2/FIL."); + + CHANGE_TO("/DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE"); + CHANGE_TO("/DIR1/DIR2/FILE2", "/tmp/qemu-test_path/DIR1/DIR2/FILE2"); + CHANGE_TO("/DIR1/DIR2/FILE3", "/tmp/qemu-test_path/DIR1/DIR2/FILE3"); + CHANGE_TO("/DIR1/DIR2/FILE4", "/tmp/qemu-test_path/DIR1/DIR2/FILE4"); + CHANGE_TO("/DIR1/DIR2/FILE5", "/tmp/qemu-test_path/DIR1/DIR2/FILE5"); + + NO_CHANGE("/DIR1/DIR2/FILE6"); + NO_CHANGE("/DIR1/DIR2/FILE/X"); + + CHANGE_TO("/DIR1/../DIR1", "/tmp/qemu-test_path/DIR1"); + CHANGE_TO("/DIR1/../DIR1/", "/tmp/qemu-test_path/DIR1"); + CHANGE_TO("/../DIR1", "/tmp/qemu-test_path/DIR1"); + CHANGE_TO("/../DIR1/", "/tmp/qemu-test_path/DIR1"); + CHANGE_TO("/DIR1/DIR2/../DIR2", "/tmp/qemu-test_path/DIR1/DIR2"); + CHANGE_TO("/DIR1/DIR2/../DIR2/../../DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE"); + CHANGE_TO("/DIR1/DIR2/../DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE"); + + NO_CHANGE("/DIR1/DIR2/../DIR1"); + NO_CHANGE("/DIR1/DIR2/../FILE"); + + CHANGE_TO("/./DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE"); + CHANGE_TO("/././DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE"); + CHANGE_TO("/DIR1/./DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE"); + CHANGE_TO("/DIR1/././DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE"); + CHANGE_TO("/DIR1/DIR2/./FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE"); + CHANGE_TO("/DIR1/DIR2/././FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE"); + CHANGE_TO("/./DIR1/./DIR2/./FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE"); + + return 0; +} + +int main(int argc, char *argv[]) +{ + int ret; + + ret = do_test(); + cleanup(); + if (ret) { + fprintf(stderr, "test_path: failed on line %i\n", ret); + return 1; + } + return 0; +} + diff --git a/tools/ioemu/tests/testthread.c b/tools/ioemu/tests/testthread.c new file mode 100644 index 0000000000..27e4825bc6 --- /dev/null +++ b/tools/ioemu/tests/testthread.c @@ -0,0 +1,51 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void *thread1_func(void *arg) +{ + int i; + char buf[512]; + + for(i=0;i<10;i++) { + snprintf(buf, sizeof(buf), "thread1: %d %s\n", i, (char *)arg); + write(1, buf, strlen(buf)); + usleep(100 * 1000); + } + return NULL; +} + +void *thread2_func(void *arg) +{ + int i; + char buf[512]; + for(i=0;i<20;i++) { + snprintf(buf, sizeof(buf), "thread2: %d %s\n", i, (char *)arg); + write(1, buf, strlen(buf)); + usleep(150 * 1000); + } + return NULL; +} + +void test_pthread(void) +{ + pthread_t tid1, tid2; + + pthread_create(&tid1, NULL, thread1_func, "hello1"); + pthread_create(&tid2, NULL, thread2_func, "hello2"); + pthread_join(tid1, NULL); + pthread_join(tid2, NULL); + printf("End of pthread test.\n"); +} + +int main(int argc, char **argv) +{ + test_pthread(); + return 0; +} diff --git a/tools/ioemu/texi2pod.pl b/tools/ioemu/texi2pod.pl new file mode 100755 index 0000000000..176627e9b9 --- /dev/null +++ b/tools/ioemu/texi2pod.pl @@ -0,0 +1,428 @@ +#! /usr/bin/perl -w + +# Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + +# This file is part of GNU CC. + +# GNU CC is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# GNU CC is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with GNU CC; see the file COPYING. If not, write to +# the Free Software Foundation, 59 Temple Place - Suite 330, +# Boston MA 02111-1307, USA. + +# This does trivial (and I mean _trivial_) conversion of Texinfo +# markup to Perl POD format. It's intended to be used to extract +# something suitable for a manpage from a Texinfo document. + +$output = 0; +$skipping = 0; +%sects = (); +$section = ""; +@icstack = (); +@endwstack = (); +@skstack = (); +@instack = (); +$shift = ""; +%defs = (); +$fnno = 1; +$inf = ""; +$ibase = ""; + +while ($_ = shift) { + if (/^-D(.*)$/) { + if ($1 ne "") { + $flag = $1; + } else { + $flag = shift; + } + $value = ""; + ($flag, $value) = ($flag =~ /^([^=]+)(?:=(.+))?/); + die "no flag specified for -D\n" + unless $flag ne ""; + die "flags may only contain letters, digits, hyphens, dashes and underscores\n" + unless $flag =~ /^[a-zA-Z0-9_-]+$/; + $defs{$flag} = $value; + } elsif (/^-/) { + usage(); + } else { + $in = $_, next unless defined $in; + $out = $_, next unless defined $out; + usage(); + } +} + +if (defined $in) { + $inf = gensym(); + open($inf, "<$in") or die "opening \"$in\": $!\n"; + $ibase = $1 if $in =~ m|^(.+)/[^/]+$|; +} else { + $inf = \*STDIN; +} + +if (defined $out) { + open(STDOUT, ">$out") or die "opening \"$out\": $!\n"; +} + +while(defined $inf) { +while(<$inf>) { + # Certain commands are discarded without further processing. + /^\@(?: + [a-z]+index # @*index: useful only in complete manual + |need # @need: useful only in printed manual + |(?:end\s+)?group # @group .. @end group: ditto + |page # @page: ditto + |node # @node: useful only in .info file + |(?:end\s+)?ifnottex # @ifnottex .. @end ifnottex: use contents + )\b/x and next; + + chomp; + + # Look for filename and title markers. + /^\@setfilename\s+([^.]+)/ and $fn = $1, next; + /^\@settitle\s+([^.]+)/ and $tl = postprocess($1), next; + + # Identify a man title but keep only the one we are interested in. + /^\@c\s+man\s+title\s+([A-Za-z0-9-]+)\s+(.+)/ and do { + if (exists $defs{$1}) { + $fn = $1; + $tl = postprocess($2); + } + next; + }; + + # Look for blocks surrounded by @c man begin SECTION ... @c man end. + # This really oughta be @ifman ... @end ifman and the like, but such + # would require rev'ing all other Texinfo translators. + /^\@c\s+man\s+begin\s+([A-Z]+)\s+([A-Za-z0-9-]+)/ and do { + $output = 1 if exists $defs{$2}; + $sect = $1; + next; + }; + /^\@c\s+man\s+begin\s+([A-Z]+)/ and $sect = $1, $output = 1, next; + /^\@c\s+man\s+end/ and do { + $sects{$sect} = "" unless exists $sects{$sect}; + $sects{$sect} .= postprocess($section); + $section = ""; + $output = 0; + next; + }; + + # handle variables + /^\@set\s+([a-zA-Z0-9_-]+)\s*(.*)$/ and do { + $defs{$1} = $2; + next; + }; + /^\@clear\s+([a-zA-Z0-9_-]+)/ and do { + delete $defs{$1}; + next; + }; + + next unless $output; + + # Discard comments. (Can't do it above, because then we'd never see + # @c man lines.) + /^\@c\b/ and next; + + # End-block handler goes up here because it needs to operate even + # if we are skipping. + /^\@end\s+([a-z]+)/ and do { + # Ignore @end foo, where foo is not an operation which may + # cause us to skip, if we are presently skipping. + my $ended = $1; + next if $skipping && $ended !~ /^(?:ifset|ifclear|ignore|menu|iftex)$/; + + die "\@end $ended without \@$ended at line $.\n" unless defined $endw; + die "\@$endw ended by \@end $ended at line $.\n" unless $ended eq $endw; + + $endw = pop @endwstack; + + if ($ended =~ /^(?:ifset|ifclear|ignore|menu|iftex)$/) { + $skipping = pop @skstack; + next; + } elsif ($ended =~ /^(?:example|smallexample|display)$/) { + $shift = ""; + $_ = ""; # need a paragraph break + } elsif ($ended =~ /^(?:itemize|enumerate|[fv]?table)$/) { + $_ = "\n=back\n"; + $ic = pop @icstack; + } else { + die "unknown command \@end $ended at line $.\n"; + } + }; + + # We must handle commands which can cause skipping even while we + # are skipping, otherwise we will not process nested conditionals + # correctly. + /^\@ifset\s+([a-zA-Z0-9_-]+)/ and do { + push @endwstack, $endw; + push @skstack, $skipping; + $endw = "ifset"; + $skipping = 1 unless exists $defs{$1}; + next; + }; + + /^\@ifclear\s+([a-zA-Z0-9_-]+)/ and do { + push @endwstack, $endw; + push @skstack, $skipping; + $endw = "ifclear"; + $skipping = 1 if exists $defs{$1}; + next; + }; + + /^\@(ignore|menu|iftex)\b/ and do { + push @endwstack, $endw; + push @skstack, $skipping; + $endw = $1; + $skipping = 1; + next; + }; + + next if $skipping; + + # Character entities. First the ones that can be replaced by raw text + # or discarded outright: + s/\@copyright\{\}/(c)/g; + s/\@dots\{\}/.../g; + s/\@enddots\{\}/..../g; + s/\@([.!? ])/$1/g; + s/\@[:-]//g; + s/\@bullet(?:\{\})?/*/g; + s/\@TeX\{\}/TeX/g; + s/\@pounds\{\}/\#/g; + s/\@minus(?:\{\})?/-/g; + s/\\,/,/g; + + # Now the ones that have to be replaced by special escapes + # (which will be turned back into text by unmunge()) + s/&/&/g; + s/\@\{/{/g; + s/\@\}/}/g; + s/\@\@/&at;/g; + + # Inside a verbatim block, handle @var specially. + if ($shift ne "") { + s/\@var\{([^\}]*)\}/<$1>/g; + } + + # POD doesn't interpret E<> inside a verbatim block. + if ($shift eq "") { + s//>/g; + } else { + s//>/g; + } + + # Single line command handlers. + + /^\@include\s+(.+)$/ and do { + push @instack, $inf; + $inf = gensym(); + + # Try cwd and $ibase. + open($inf, "<" . $1) + or open($inf, "<" . $ibase . "/" . $1) + or die "cannot open $1 or $ibase/$1: $!\n"; + next; + }; + + /^\@(?:section|unnumbered|unnumberedsec|center)\s+(.+)$/ + and $_ = "\n=head2 $1\n"; + /^\@subsection\s+(.+)$/ + and $_ = "\n=head3 $1\n"; + + # Block command handlers: + /^\@itemize\s+(\@[a-z]+|\*|-)/ and do { + push @endwstack, $endw; + push @icstack, $ic; + $ic = $1; + $_ = "\n=over 4\n"; + $endw = "itemize"; + }; + + /^\@enumerate(?:\s+([a-zA-Z0-9]+))?/ and do { + push @endwstack, $endw; + push @icstack, $ic; + if (defined $1) { + $ic = $1 . "."; + } else { + $ic = "1."; + } + $_ = "\n=over 4\n"; + $endw = "enumerate"; + }; + + /^\@([fv]?table)\s+(\@[a-z]+)/ and do { + push @endwstack, $endw; + push @icstack, $ic; + $endw = $1; + $ic = $2; + $ic =~ s/\@(?:samp|strong|key|gcctabopt|option|env)/B/; + $ic =~ s/\@(?:code|kbd)/C/; + $ic =~ s/\@(?:dfn|var|emph|cite|i)/I/; + $ic =~ s/\@(?:file)/F/; + $_ = "\n=over 4\n"; + }; + + /^\@((?:small)?example|display)/ and do { + push @endwstack, $endw; + $endw = $1; + $shift = "\t"; + $_ = ""; # need a paragraph break + }; + + /^\@itemx?\s*(.+)?$/ and do { + if (defined $1) { + # Entity escapes prevent munging by the <> processing below. +# print "$ic\n"; + $_ = "\n=item $ic\<$1\>\n"; + } else { + $_ = "\n=item $ic\n"; + $ic =~ y/A-Ya-y/B-Zb-z/; + $ic =~ s/(\d+)/$1 + 1/eg; + } + }; + + $section .= $shift.$_."\n"; +} +# End of current file. +close($inf); +$inf = pop @instack; +} + +die "No filename or title\n" unless defined $fn && defined $tl; + +$sects{NAME} = "$fn \- $tl\n"; +$sects{FOOTNOTES} .= "=back\n" if exists $sects{FOOTNOTES}; + +for $sect (qw(NAME SYNOPSIS DESCRIPTION OPTIONS ENVIRONMENT FILES + BUGS NOTES FOOTNOTES SEEALSO AUTHOR COPYRIGHT)) { + if(exists $sects{$sect}) { + $head = $sect; + $head =~ s/SEEALSO/SEE ALSO/; + print "=head1 $head\n\n"; + print scalar unmunge ($sects{$sect}); + print "\n"; + } +} + +sub usage +{ + die "usage: $0 [-D toggle...] [infile [outfile]]\n"; +} + +sub postprocess +{ + local $_ = $_[0]; + + # @value{foo} is replaced by whatever 'foo' is defined as. + while (m/(\@value\{([a-zA-Z0-9_-]+)\})/g) { + if (! exists $defs{$2}) { + print STDERR "Option $2 not defined\n"; + s/\Q$1\E//; + } else { + $value = $defs{$2}; + s/\Q$1\E/$value/; + } + } + + # Formatting commands. + # Temporary escape for @r. + s/\@r\{([^\}]*)\}/R<$1>/g; + s/\@(?:dfn|var|emph|cite|i)\{([^\}]*)\}/I<$1>/g; + s/\@(?:code|kbd)\{([^\}]*)\}/C<$1>/g; + s/\@(?:gccoptlist|samp|strong|key|option|env|command|b)\{([^\}]*)\}/B<$1>/g; + s/\@sc\{([^\}]*)\}/\U$1/g; + s/\@file\{([^\}]*)\}/F<$1>/g; + s/\@w\{([^\}]*)\}/S<$1>/g; + s/\@(?:dmn|math)\{([^\}]*)\}/$1/g; + + # Cross references are thrown away, as are @noindent and @refill. + # (@noindent is impossible in .pod, and @refill is unnecessary.) + # @* is also impossible in .pod; we discard it and any newline that + # follows it. Similarly, our macro @gol must be discarded. + + s/\(?\@xref\{(?:[^\}]*)\}(?:[^.<]|(?:<[^<>]*>))*\.\)?//g; + s/\s+\(\@pxref\{(?:[^\}]*)\}\)//g; + s/;\s+\@pxref\{(?:[^\}]*)\}//g; + s/\@noindent\s*//g; + s/\@refill//g; + s/\@gol//g; + s/\@\*\s*\n?//g; + + # @uref can take one, two, or three arguments, with different + # semantics each time. @url and @email are just like @uref with + # one argument, for our purposes. + s/\@(?:uref|url|email)\{([^\},]*)\}/<B<$1>>/g; + s/\@uref\{([^\},]*),([^\},]*)\}/$2 (C<$1>)/g; + s/\@uref\{([^\},]*),([^\},]*),([^\},]*)\}/$3/g; + + # Turn B blah> into B I B to + # match Texinfo semantics of @emph inside @samp. Also handle @r + # inside bold. + s/</
/g; + 1 while s/B<((?:[^<>]|I<[^<>]*>)*)R<([^>]*)>/B<$1>${2}B]*)I<([^>]+)>/B<$1>I<$2>B]*)B<([^>]+)>/I<$1>B<$2>I//g; + s/([BI])<(\s+)([^>]+)>/$2$1<$3>/g; + s/([BI])<([^>]+?)(\s+)>/$1<$2>$3/g; + + # Extract footnotes. This has to be done after all other + # processing because otherwise the regexp will choke on formatting + # inside @footnote. + while (/\@footnote/g) { + s/\@footnote\{([^\}]+)\}/[$fnno]/; + add_footnote($1, $fnno); + $fnno++; + } + + return $_; +} + +sub unmunge +{ + # Replace escaped symbols with their equivalents. + local $_ = $_[0]; + + s/</E/g; + s/>/E/g; + s/{/\{/g; + s/}/\}/g; + s/&at;/\@/g; + s/&/&/g; + return $_; +} + +sub add_footnote +{ + unless (exists $sects{FOOTNOTES}) { + $sects{FOOTNOTES} = "\n=over 4\n\n"; + } + + $sects{FOOTNOTES} .= "=item $fnno.\n\n"; $fnno++; + $sects{FOOTNOTES} .= $_[0]; + $sects{FOOTNOTES} .= "\n\n"; +} + +# stolen from Symbol.pm +{ + my $genseq = 0; + sub gensym + { + my $name = "GEN" . $genseq++; + my $ref = \*{$name}; + delete $::{$name}; + return $ref; + } +} diff --git a/tools/ioemu/thunk.c b/tools/ioemu/thunk.c new file mode 100644 index 0000000000..2dbc378cd9 --- /dev/null +++ b/tools/ioemu/thunk.c @@ -0,0 +1,243 @@ +/* + * Generic thunking code to convert data between host and target CPU + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include +#include +#include + +#include "qemu.h" +#include "thunk.h" + +//#define DEBUG + +#define MAX_STRUCTS 128 + +/* XXX: make it dynamic */ +StructEntry struct_entries[MAX_STRUCTS]; + +static inline const argtype *thunk_type_next(const argtype *type_ptr) +{ + int type; + + type = *type_ptr++; + switch(type) { + case TYPE_CHAR: + case TYPE_SHORT: + case TYPE_INT: + case TYPE_LONGLONG: + case TYPE_ULONGLONG: + case TYPE_LONG: + case TYPE_ULONG: + case TYPE_PTRVOID: + return type_ptr; + case TYPE_PTR: + return thunk_type_next(type_ptr); + case TYPE_ARRAY: + return thunk_type_next(type_ptr + 1); + case TYPE_STRUCT: + return type_ptr + 1; + default: + return NULL; + } +} + +void thunk_register_struct(int id, const char *name, const argtype *types) +{ + const argtype *type_ptr; + StructEntry *se; + int nb_fields, offset, max_align, align, size, i, j; + + se = struct_entries + id; + + /* first we count the number of fields */ + type_ptr = types; + nb_fields = 0; + while (*type_ptr != TYPE_NULL) { + type_ptr = thunk_type_next(type_ptr); + nb_fields++; + } + se->field_types = types; + se->nb_fields = nb_fields; + se->name = name; +#ifdef DEBUG + printf("struct %s: id=%d nb_fields=%d\n", + se->name, id, se->nb_fields); +#endif + /* now we can alloc the data */ + + for(i = 0;i < 2; i++) { + offset = 0; + max_align = 1; + se->field_offsets[i] = malloc(nb_fields * sizeof(int)); + type_ptr = se->field_types; + for(j = 0;j < nb_fields; j++) { + size = thunk_type_size(type_ptr, i); + align = thunk_type_align(type_ptr, i); + offset = (offset + align - 1) & ~(align - 1); + se->field_offsets[i][j] = offset; + offset += size; + if (align > max_align) + max_align = align; + type_ptr = thunk_type_next(type_ptr); + } + offset = (offset + max_align - 1) & ~(max_align - 1); + se->size[i] = offset; + se->align[i] = max_align; +#ifdef DEBUG + printf("%s: size=%d align=%d\n", + i == THUNK_HOST ? "host" : "target", offset, max_align); +#endif + } +} + +void thunk_register_struct_direct(int id, const char *name, StructEntry *se1) +{ + StructEntry *se; + se = struct_entries + id; + *se = *se1; + se->name = name; +} + + +/* now we can define the main conversion functions */ +const argtype *thunk_convert(void *dst, const void *src, + const argtype *type_ptr, int to_host) +{ + int type; + + type = *type_ptr++; + switch(type) { + case TYPE_CHAR: + *(uint8_t *)dst = *(uint8_t *)src; + break; + case TYPE_SHORT: + *(uint16_t *)dst = tswap16(*(uint16_t *)src); + break; + case TYPE_INT: + *(uint32_t *)dst = tswap32(*(uint32_t *)src); + break; + case TYPE_LONGLONG: + case TYPE_ULONGLONG: + *(uint64_t *)dst = tswap64(*(uint64_t *)src); + break; +#if HOST_LONG_BITS == 32 && TARGET_LONG_BITS == 32 + case TYPE_LONG: + case TYPE_ULONG: + case TYPE_PTRVOID: + *(uint32_t *)dst = tswap32(*(uint32_t *)src); + break; +#elif HOST_LONG_BITS == 64 && TARGET_LONG_BITS == 32 + case TYPE_LONG: + case TYPE_ULONG: + case TYPE_PTRVOID: + if (to_host) { + *(uint64_t *)dst = tswap32(*(uint32_t *)src); + } else { + *(uint32_t *)dst = tswap32(*(uint64_t *)src & 0xffffffff); + } + break; +#else +#error unsupported conversion +#endif + case TYPE_ARRAY: + { + int array_length, i, dst_size, src_size; + const uint8_t *s; + uint8_t *d; + + array_length = *type_ptr++; + dst_size = thunk_type_size(type_ptr, to_host); + src_size = thunk_type_size(type_ptr, 1 - to_host); + d = dst; + s = src; + for(i = 0;i < array_length; i++) { + thunk_convert(d, s, type_ptr, to_host); + d += dst_size; + s += src_size; + } + type_ptr = thunk_type_next(type_ptr); + } + break; + case TYPE_STRUCT: + { + int i; + const StructEntry *se; + const uint8_t *s; + uint8_t *d; + const argtype *field_types; + const int *dst_offsets, *src_offsets; + + se = struct_entries + *type_ptr++; + if (se->convert[0] != NULL) { + /* specific conversion is needed */ + (*se->convert[to_host])(dst, src); + } else { + /* standard struct conversion */ + field_types = se->field_types; + dst_offsets = se->field_offsets[to_host]; + src_offsets = se->field_offsets[1 - to_host]; + d = dst; + s = src; + for(i = 0;i < se->nb_fields; i++) { + field_types = thunk_convert(d + dst_offsets[i], + s + src_offsets[i], + field_types, to_host); + } + } + } + break; + default: + fprintf(stderr, "Invalid type 0x%x\n", type); + break; + } + return type_ptr; +} + +/* from em86 */ + +/* Utility function: Table-driven functions to translate bitmasks + * between X86 and Alpha formats... + */ +unsigned int target_to_host_bitmask(unsigned int x86_mask, + bitmask_transtbl * trans_tbl) +{ + bitmask_transtbl * btp; + unsigned int alpha_mask = 0; + + for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) { + if((x86_mask & btp->x86_mask) == btp->x86_bits) { + alpha_mask |= btp->alpha_bits; + } + } + return(alpha_mask); +} + +unsigned int host_to_target_bitmask(unsigned int alpha_mask, + bitmask_transtbl * trans_tbl) +{ + bitmask_transtbl * btp; + unsigned int x86_mask = 0; + + for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) { + if((alpha_mask & btp->alpha_mask) == btp->alpha_bits) { + x86_mask |= btp->x86_bits; + } + } + return(x86_mask); +} diff --git a/tools/ioemu/thunk.h b/tools/ioemu/thunk.h new file mode 100644 index 0000000000..42fd96f3a3 --- /dev/null +++ b/tools/ioemu/thunk.h @@ -0,0 +1,158 @@ +/* + * Generic thunking code to convert data between host and target CPU + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef THUNK_H +#define THUNK_H + +#include +#include "cpu.h" + +/* types enums definitions */ + +typedef enum argtype { + TYPE_NULL, + TYPE_CHAR, + TYPE_SHORT, + TYPE_INT, + TYPE_LONG, + TYPE_ULONG, + TYPE_PTRVOID, /* pointer on unknown data */ + TYPE_LONGLONG, + TYPE_ULONGLONG, + TYPE_PTR, + TYPE_ARRAY, + TYPE_STRUCT, +} argtype; + +#define MK_PTR(type) TYPE_PTR, type +#define MK_ARRAY(type, size) TYPE_ARRAY, size, type +#define MK_STRUCT(id) TYPE_STRUCT, id + +#define THUNK_TARGET 0 +#define THUNK_HOST 1 + +typedef struct { + /* standard struct handling */ + const argtype *field_types; + int nb_fields; + int *field_offsets[2]; + /* special handling */ + void (*convert[2])(void *dst, const void *src); + int size[2]; + int align[2]; + const char *name; +} StructEntry; + +/* Translation table for bitmasks... */ +typedef struct bitmask_transtbl { + unsigned int x86_mask; + unsigned int x86_bits; + unsigned int alpha_mask; + unsigned int alpha_bits; +} bitmask_transtbl; + +void thunk_register_struct(int id, const char *name, const argtype *types); +void thunk_register_struct_direct(int id, const char *name, StructEntry *se1); +const argtype *thunk_convert(void *dst, const void *src, + const argtype *type_ptr, int to_host); +#ifndef NO_THUNK_TYPE_SIZE + +extern StructEntry struct_entries[]; + +static inline int thunk_type_size(const argtype *type_ptr, int is_host) +{ + int type, size; + const StructEntry *se; + + type = *type_ptr; + switch(type) { + case TYPE_CHAR: + return 1; + case TYPE_SHORT: + return 2; + case TYPE_INT: + return 4; + case TYPE_LONGLONG: + case TYPE_ULONGLONG: + return 8; + case TYPE_LONG: + case TYPE_ULONG: + case TYPE_PTRVOID: + case TYPE_PTR: + if (is_host) { + return HOST_LONG_SIZE; + } else { + return TARGET_LONG_SIZE; + } + break; + case TYPE_ARRAY: + size = type_ptr[1]; + return size * thunk_type_size(type_ptr + 2, is_host); + case TYPE_STRUCT: + se = struct_entries + type_ptr[1]; + return se->size[is_host]; + default: + return -1; + } +} + +static inline int thunk_type_align(const argtype *type_ptr, int is_host) +{ + int type; + const StructEntry *se; + + type = *type_ptr; + switch(type) { + case TYPE_CHAR: + return 1; + case TYPE_SHORT: + return 2; + case TYPE_INT: + return 4; + case TYPE_LONGLONG: + case TYPE_ULONGLONG: + return 8; + case TYPE_LONG: + case TYPE_ULONG: + case TYPE_PTRVOID: + case TYPE_PTR: + if (is_host) { + return HOST_LONG_SIZE; + } else { + return TARGET_LONG_SIZE; + } + break; + case TYPE_ARRAY: + return thunk_type_align(type_ptr + 2, is_host); + case TYPE_STRUCT: + se = struct_entries + type_ptr[1]; + return se->align[is_host]; + default: + return -1; + } +} + +#endif /* NO_THUNK_TYPE_SIZE */ + +unsigned int target_to_host_bitmask(unsigned int x86_mask, + bitmask_transtbl * trans_tbl); +unsigned int host_to_target_bitmask(unsigned int alpha_mask, + bitmask_transtbl * trans_tbl); + +#endif diff --git a/tools/ioemu/vgafont.h b/tools/ioemu/vgafont.h new file mode 100644 index 0000000000..bb75796be5 --- /dev/null +++ b/tools/ioemu/vgafont.h @@ -0,0 +1,4611 @@ +static uint8_t vgafont16[256 * 16] = { + + /* 0 0x00 '^@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 1 0x01 '^A' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x81, /* 10000001 */ + 0xa5, /* 10100101 */ + 0x81, /* 10000001 */ + 0x81, /* 10000001 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0x81, /* 10000001 */ + 0x81, /* 10000001 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 2 0x02 '^B' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xdb, /* 11011011 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 3 0x03 '^C' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 4 0x04 '^D' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 5 0x05 '^E' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0xe7, /* 11100111 */ + 0xe7, /* 11100111 */ + 0xe7, /* 11100111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 6 0x06 '^F' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 7 0x07 '^G' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 8 0x08 '^H' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xe7, /* 11100111 */ + 0xc3, /* 11000011 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 9 0x09 '^I' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x42, /* 01000010 */ + 0x42, /* 01000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 10 0x0a '^J' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0x99, /* 10011001 */ + 0xbd, /* 10111101 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0xc3, /* 11000011 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 11 0x0b '^K' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1e, /* 00011110 */ + 0x0e, /* 00001110 */ + 0x1a, /* 00011010 */ + 0x32, /* 00110010 */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 12 0x0c '^L' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 13 0x0d '^M' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x33, /* 00110011 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x70, /* 01110000 */ + 0xf0, /* 11110000 */ + 0xe0, /* 11100000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 14 0x0e '^N' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x67, /* 01100111 */ + 0xe7, /* 11100111 */ + 0xe6, /* 11100110 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 15 0x0f '^O' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xdb, /* 11011011 */ + 0x3c, /* 00111100 */ + 0xe7, /* 11100111 */ + 0x3c, /* 00111100 */ + 0xdb, /* 11011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 16 0x10 '^P' */ + 0x00, /* 00000000 */ + 0x80, /* 10000000 */ + 0xc0, /* 11000000 */ + 0xe0, /* 11100000 */ + 0xf0, /* 11110000 */ + 0xf8, /* 11111000 */ + 0xfe, /* 11111110 */ + 0xf8, /* 11111000 */ + 0xf0, /* 11110000 */ + 0xe0, /* 11100000 */ + 0xc0, /* 11000000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 17 0x11 '^Q' */ + 0x00, /* 00000000 */ + 0x02, /* 00000010 */ + 0x06, /* 00000110 */ + 0x0e, /* 00001110 */ + 0x1e, /* 00011110 */ + 0x3e, /* 00111110 */ + 0xfe, /* 11111110 */ + 0x3e, /* 00111110 */ + 0x1e, /* 00011110 */ + 0x0e, /* 00001110 */ + 0x06, /* 00000110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 18 0x12 '^R' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 19 0x13 '^S' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 20 0x14 '^T' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7f, /* 01111111 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7b, /* 01111011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 21 0x15 '^U' */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x0c, /* 00001100 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 22 0x16 '^V' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 23 0x17 '^W' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 24 0x18 '^X' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 25 0x19 '^Y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 26 0x1a '^Z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 27 0x1b '^[' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xfe, /* 11111110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 28 0x1c '^\' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 29 0x1d '^]' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x28, /* 00101000 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x28, /* 00101000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 30 0x1e '^^' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 31 0x1f '^_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 32 0x20 ' ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 33 0x21 '!' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 34 0x22 '"' */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x24, /* 00100100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 35 0x23 '#' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 36 0x24 '$' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x86, /* 10000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 37 0x25 '%' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc2, /* 11000010 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0x86, /* 10000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 38 0x26 '&' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 39 0x27 ''' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 40 0x28 '(' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 41 0x29 ')' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 42 0x2a '*' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0xff, /* 11111111 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 43 0x2b '+' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 44 0x2c ',' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 45 0x2d '-' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 46 0x2e '.' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 47 0x2f '/' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x02, /* 00000010 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 48 0x30 '0' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 49 0x31 '1' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x38, /* 00111000 */ + 0x78, /* 01111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 50 0x32 '2' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 51 0x33 '3' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x3c, /* 00111100 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 52 0x34 '4' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x1c, /* 00011100 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 53 0x35 '5' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 54 0x36 '6' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 55 0x37 '7' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 56 0x38 '8' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 57 0x39 '9' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 58 0x3a ':' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 59 0x3b ';' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 60 0x3c '<' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 61 0x3d '=' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 62 0x3e '>' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 63 0x3f '?' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 64 0x40 '@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xdc, /* 11011100 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 65 0x41 'A' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 66 0x42 'B' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 67 0x43 'C' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc2, /* 11000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 68 0x44 'D' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 69 0x45 'E' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x66, /* 01100110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x60, /* 01100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 70 0x46 'F' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x66, /* 01100110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 71 0x47 'G' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xde, /* 11011110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x66, /* 01100110 */ + 0x3a, /* 00111010 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 72 0x48 'H' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 73 0x49 'I' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 74 0x4a 'J' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1e, /* 00011110 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 75 0x4b 'K' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe6, /* 11100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 76 0x4c 'L' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 77 0x4d 'M' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xee, /* 11101110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 78 0x4e 'N' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xfe, /* 11111110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 79 0x4f 'O' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 80 0x50 'P' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 81 0x51 'Q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xde, /* 11011110 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x0e, /* 00001110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 82 0x52 'R' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 83 0x53 'S' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x38, /* 00111000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 84 0x54 'T' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x5a, /* 01011010 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 85 0x55 'U' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 86 0x56 'V' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 87 0x57 'W' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0xee, /* 11101110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 88 0x58 'X' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 89 0x59 'Y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 90 0x5a 'Z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x86, /* 10000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc2, /* 11000010 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 91 0x5b '[' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 92 0x5c '\' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x80, /* 10000000 */ + 0xc0, /* 11000000 */ + 0xe0, /* 11100000 */ + 0x70, /* 01110000 */ + 0x38, /* 00111000 */ + 0x1c, /* 00011100 */ + 0x0e, /* 00001110 */ + 0x06, /* 00000110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 93 0x5d ']' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 94 0x5e '^' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 95 0x5f '_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 96 0x60 '`' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 97 0x61 'a' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 98 0x62 'b' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 99 0x63 'c' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 100 0x64 'd' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1c, /* 00011100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 101 0x65 'e' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 102 0x66 'f' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1c, /* 00011100 */ + 0x36, /* 00110110 */ + 0x32, /* 00110010 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 103 0x67 'g' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 104 0x68 'h' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x6c, /* 01101100 */ + 0x76, /* 01110110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 105 0x69 'i' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 106 0x6a 'j' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 107 0x6b 'k' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 108 0x6c 'l' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 109 0x6d 'm' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xec, /* 11101100 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 110 0x6e 'n' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 111 0x6f 'o' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 112 0x70 'p' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 113 0x71 'q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + + /* 114 0x72 'r' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x66, /* 01100110 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 115 0x73 's' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x38, /* 00111000 */ + 0x0c, /* 00001100 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 116 0x74 't' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0xfc, /* 11111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x36, /* 00110110 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 117 0x75 'u' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 118 0x76 'v' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 119 0x77 'w' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 120 0x78 'x' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 121 0x79 'y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + + /* 122 0x7a 'z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xcc, /* 11001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 123 0x7b '{' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 124 0x7c '|' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 125 0x7d '}' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 126 0x7e '~' */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 127 0x7f '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 128 0x80 '€' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc2, /* 11000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 129 0x81 '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 130 0x82 '‚' */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 131 0x83 'ƒ' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 132 0x84 '„' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 133 0x85 '…' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 134 0x86 '†' */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 135 0x87 '‡' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 136 0x88 'ˆ' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 137 0x89 '‰' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 138 0x8a 'Š' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 139 0x8b '‹' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 140 0x8c 'Œ' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 141 0x8d '' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 142 0x8e 'Ž' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 143 0x8f '' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 144 0x90 '' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x66, /* 01100110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 145 0x91 '‘' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xec, /* 11101100 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x6e, /* 01101110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 146 0x92 '’' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3e, /* 00111110 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xce, /* 11001110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 147 0x93 '“' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 148 0x94 '”' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 149 0x95 '•' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 150 0x96 '–' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 151 0x97 '—' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 152 0x98 '˜' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 153 0x99 '™' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 154 0x9a 'š' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 155 0x9b '›' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 156 0x9c 'œ' */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x64, /* 01100100 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xe6, /* 11100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 157 0x9d '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 158 0x9e 'ž' */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xf8, /* 11111000 */ + 0xc4, /* 11000100 */ + 0xcc, /* 11001100 */ + 0xde, /* 11011110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 159 0x9f 'Ÿ' */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 160 0xa0 ' ' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 161 0xa1 '¡' */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 162 0xa2 '¢' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 163 0xa3 '£' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 164 0xa4 '¤' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 165 0xa5 '¥' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xfe, /* 11111110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 166 0xa6 '¦' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 167 0xa7 '§' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 168 0xa8 '¨' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 169 0xa9 '©' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 170 0xaa 'ª' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 171 0xab '«' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0xe0, /* 11100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xdc, /* 11011100 */ + 0x86, /* 10000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 172 0xac '¬' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0xe0, /* 11100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x66, /* 01100110 */ + 0xce, /* 11001110 */ + 0x9a, /* 10011010 */ + 0x3f, /* 00111111 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 173 0xad '­' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 174 0xae '®' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x36, /* 00110110 */ + 0x6c, /* 01101100 */ + 0xd8, /* 11011000 */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 175 0xaf '¯' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xd8, /* 11011000 */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x6c, /* 01101100 */ + 0xd8, /* 11011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 176 0xb0 '°' */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + + /* 177 0xb1 '±' */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + + /* 178 0xb2 '²' */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + + /* 179 0xb3 '³' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 180 0xb4 '´' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 181 0xb5 'µ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 182 0xb6 '¶' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 183 0xb7 '·' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 184 0xb8 '¸' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 185 0xb9 '¹' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 186 0xba 'º' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 187 0xbb '»' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 188 0xbc '¼' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 189 0xbd '½' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 190 0xbe '¾' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 191 0xbf '¿' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 192 0xc0 'À' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 193 0xc1 'Á' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 194 0xc2 'Â' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 195 0xc3 'Ã' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 196 0xc4 'Ä' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 197 0xc5 'Å' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 198 0xc6 'Æ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 199 0xc7 'Ç' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 200 0xc8 'È' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 201 0xc9 'É' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 202 0xca 'Ê' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 203 0xcb 'Ë' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 204 0xcc 'Ì' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 205 0xcd 'Í' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 206 0xce 'Î' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 207 0xcf 'Ï' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 208 0xd0 'Ð' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 209 0xd1 'Ñ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 210 0xd2 'Ò' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 211 0xd3 'Ó' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 212 0xd4 'Ô' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 213 0xd5 'Õ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 214 0xd6 'Ö' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 215 0xd7 '×' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 216 0xd8 'Ø' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 217 0xd9 'Ù' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 218 0xda 'Ú' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 219 0xdb 'Û' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 220 0xdc 'Ü' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 221 0xdd 'Ý' */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + + /* 222 0xde 'Þ' */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + + /* 223 0xdf 'ß' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 224 0xe0 'à' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 225 0xe1 'á' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xd8, /* 11011000 */ + 0xcc, /* 11001100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 226 0xe2 'â' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 227 0xe3 'ã' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 228 0xe4 'ä' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 229 0xe5 'å' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 230 0xe6 'æ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + + /* 231 0xe7 'ç' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 232 0xe8 'è' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 233 0xe9 'é' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 234 0xea 'ê' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xee, /* 11101110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 235 0xeb 'ë' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1e, /* 00011110 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x3e, /* 00111110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 236 0xec 'ì' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 237 0xed 'í' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x03, /* 00000011 */ + 0x06, /* 00000110 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0xf3, /* 11110011 */ + 0x7e, /* 01111110 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 238 0xee 'î' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1c, /* 00011100 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 239 0xef 'ï' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 240 0xf0 'ð' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 241 0xf1 'ñ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 242 0xf2 'ò' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 243 0xf3 'ó' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 244 0xf4 'ô' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 245 0xf5 'õ' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 246 0xf6 'ö' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 247 0xf7 '÷' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 248 0xf8 'ø' */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 249 0xf9 'ù' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 250 0xfa 'ú' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 251 0xfb 'û' */ + 0x00, /* 00000000 */ + 0x0f, /* 00001111 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xec, /* 11101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x3c, /* 00111100 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 252 0xfc 'ü' */ + 0x00, /* 00000000 */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 253 0xfd 'ý' */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x32, /* 00110010 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 254 0xfe 'þ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 255 0xff 'ÿ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + +}; diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c new file mode 100644 index 0000000000..f6c6e005c0 --- /dev/null +++ b/tools/ioemu/vl.c @@ -0,0 +1,2978 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +#include +#include +#include +#include +#include +#include + +#ifndef _WIN32 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef _BSD +#include +#ifndef __APPLE__ +#include +#endif +#else +#include +#include +#include +#include +#include +#endif +#endif + +#if defined(CONFIG_SLIRP) +#include "libslirp.h" +#endif + +#ifdef _WIN32 +#include +#include +#include +#define getopt_long_only getopt_long +#define memalign(align, size) malloc(size) +#endif + +#ifdef CONFIG_SDL +#ifdef __APPLE__ +#include +#endif +#endif /* CONFIG_SDL */ + +#include "xc.h" +#include "exec-all.h" + +//#define DO_TB_FLUSH + +#define DEFAULT_NETWORK_SCRIPT "/etc/xen/qemu-ifup" + +#if !defined(CONFIG_SOFTMMU) +#define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) +#else +#define PHYS_RAM_MAX_SIZE (2047 * 1024 * 1024) +#endif + +#ifdef TARGET_PPC +#define DEFAULT_RAM_SIZE 144 +#else +#define DEFAULT_RAM_SIZE 128 +#endif +/* in ms */ +#define GUI_REFRESH_INTERVAL 30 +#define POLLING_INTERVAL 5 + +/* XXX: use a two level table to limit memory usage */ +#define MAX_IOPORTS 65536 + +const char *bios_dir = CONFIG_QEMU_SHAREDIR; +char phys_ram_file[1024]; +CPUState *global_env; +CPUState *cpu_single_env; +void *ioport_opaque[MAX_IOPORTS]; +IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; +IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; +BlockDriverState *bs_table[MAX_DISKS], *fd_table[MAX_FD]; +int vga_ram_size; +int bios_size; +static DisplayState display_state; +int nographic; +int usevnc; /* 1=vnc only, 2=vnc and sdl */ +const char* keyboard_layout = 0; +int64_t ticks_per_sec; +int boot_device = 'c'; +int ram_size; +int domid; +static char network_script[1024]; +int pit_min_timer_count = 0; +int nb_nics; +NetDriverState nd_table[MAX_NICS]; +QEMUTimer *gui_timer; +QEMUTimer *polling_timer; +int vm_running; +int audio_enabled = 0; +int sb16_enabled = 1; +int adlib_enabled = 1; +int gus_enabled = 1; +int pci_enabled = 1; +int prep_enabled = 0; +int rtc_utc = 1; +int cirrus_vga_enabled = 1; +int graphic_width = 800; +int graphic_height = 600; +int graphic_depth = 15; +int full_screen = 0; +TextConsole *vga_console; +CharDriverState *serial_hds[MAX_SERIAL_PORTS]; +int xc_handle; + +/***********************************************************/ +/* x86 ISA bus support */ + +target_phys_addr_t isa_mem_base = 0; + +uint32_t default_ioport_readb(void *opaque, uint32_t address) +{ +#ifdef DEBUG_UNUSED_IOPORT + fprintf(stderr, "inb: port=0x%04x\n", address); +#endif + return 0xff; +} + +void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data) +{ +#ifdef DEBUG_UNUSED_IOPORT + fprintf(stderr, "outb: port=0x%04x data=0x%02x\n", address, data); +#endif +} + +/* default is to make two byte accesses */ +uint32_t default_ioport_readw(void *opaque, uint32_t address) +{ + uint32_t data; + data = ioport_read_table[0][address](ioport_opaque[address], address); + address = (address + 1) & (MAX_IOPORTS - 1); + data |= ioport_read_table[0][address](ioport_opaque[address], address) << 8; + return data; +} + +void default_ioport_writew(void *opaque, uint32_t address, uint32_t data) +{ + ioport_write_table[0][address](ioport_opaque[address], address, data & 0xff); + address = (address + 1) & (MAX_IOPORTS - 1); + ioport_write_table[0][address](ioport_opaque[address], address, (data >> 8) & 0xff); +} + +uint32_t default_ioport_readl(void *opaque, uint32_t address) +{ +#ifdef DEBUG_UNUSED_IOPORT + fprintf(stderr, "inl: port=0x%04x\n", address); +#endif + return 0xffffffff; +} + +void default_ioport_writel(void *opaque, uint32_t address, uint32_t data) +{ +#ifdef DEBUG_UNUSED_IOPORT + fprintf(stderr, "outl: port=0x%04x data=0x%02x\n", address, data); +#endif +} + +void init_ioports(void) +{ + int i; + + for(i = 0; i < MAX_IOPORTS; i++) { + ioport_read_table[0][i] = default_ioport_readb; + ioport_write_table[0][i] = default_ioport_writeb; + ioport_read_table[1][i] = default_ioport_readw; + ioport_write_table[1][i] = default_ioport_writew; + ioport_read_table[2][i] = default_ioport_readl; + ioport_write_table[2][i] = default_ioport_writel; + } +} + +/* size is the word size in byte */ +int register_ioport_read(int start, int length, int size, + IOPortReadFunc *func, void *opaque) +{ + int i, bsize; + + if (size == 1) { + bsize = 0; + } else if (size == 2) { + bsize = 1; + } else if (size == 4) { + bsize = 2; + } else { + hw_error("register_ioport_read: invalid size"); + return -1; + } + for(i = start; i < start + length; i += size) { + ioport_read_table[bsize][i] = func; + if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque) + hw_error("register_ioport_read: invalid opaque"); + ioport_opaque[i] = opaque; + } + return 0; +} + +/* size is the word size in byte */ +int register_ioport_write(int start, int length, int size, + IOPortWriteFunc *func, void *opaque) +{ + int i, bsize; + + if (size == 1) { + bsize = 0; + } else if (size == 2) { + bsize = 1; + } else if (size == 4) { + bsize = 2; + } else { + hw_error("register_ioport_write: invalid size"); + return -1; + } + for(i = start; i < start + length; i += size) { + ioport_write_table[bsize][i] = func; + if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque) + hw_error("register_ioport_read: invalid opaque"); + ioport_opaque[i] = opaque; + } + return 0; +} + +void isa_unassign_ioport(int start, int length) +{ + int i; + + for(i = start; i < start + length; i++) { + ioport_read_table[0][i] = default_ioport_readb; + ioport_read_table[1][i] = default_ioport_readw; + ioport_read_table[2][i] = default_ioport_readl; + + ioport_write_table[0][i] = default_ioport_writeb; + ioport_write_table[1][i] = default_ioport_writew; + ioport_write_table[2][i] = default_ioport_writel; + } +} + +void pstrcpy(char *buf, int buf_size, const char *str) +{ + int c; + char *q = buf; + + if (buf_size <= 0) + return; + + for(;;) { + c = *str++; + if (c == 0 || q >= buf + buf_size - 1) + break; + *q++ = c; + } + *q = '\0'; +} + +/* strcat and truncate. */ +char *pstrcat(char *buf, int buf_size, const char *s) +{ + int len; + len = strlen(buf); + if (len < buf_size) + pstrcpy(buf + len, buf_size - len, s); + return buf; +} + +int strstart(const char *str, const char *val, const char **ptr) +{ + const char *p, *q; + p = str; + q = val; + while (*q != '\0') { + if (*p != *q) + return 0; + p++; + q++; + } + if (ptr) + *ptr = p; + return 1; +} + +/* return the size or -1 if error */ +int get_image_size(const char *filename) +{ + int fd, size; + fd = open(filename, O_RDONLY | O_BINARY); + if (fd < 0) + return -1; + size = lseek(fd, 0, SEEK_END); + close(fd); + return size; +} + +/* return the size or -1 if error */ +int load_image(const char *filename, uint8_t *addr) +{ + int fd, size; + fd = open(filename, O_RDONLY | O_BINARY); + if (fd < 0) + return -1; + size = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + if (read(fd, addr, size) != size) { + close(fd); + return -1; + } + close(fd); + return size; +} + +void cpu_outb(CPUState *env, int addr, int val) +{ +#ifdef DEBUG_IOPORT + if (loglevel & CPU_LOG_IOPORT) + fprintf(logfile, "outb: %04x %02x\n", addr, val); +#endif + ioport_write_table[0][addr](ioport_opaque[addr], addr, val); +} + +void cpu_outw(CPUState *env, int addr, int val) +{ +#ifdef DEBUG_IOPORT + if (loglevel & CPU_LOG_IOPORT) + fprintf(logfile, "outw: %04x %04x\n", addr, val); +#endif + ioport_write_table[1][addr](ioport_opaque[addr], addr, val); +} + +void cpu_outl(CPUState *env, int addr, int val) +{ +#ifdef DEBUG_IOPORT + if (loglevel & CPU_LOG_IOPORT) + fprintf(logfile, "outl: %04x %08x\n", addr, val); +#endif + ioport_write_table[2][addr](ioport_opaque[addr], addr, val); +} + +int cpu_inb(CPUState *env, int addr) +{ + int val; + val = ioport_read_table[0][addr](ioport_opaque[addr], addr); +#ifdef DEBUG_IOPORT + if (loglevel & CPU_LOG_IOPORT) + fprintf(logfile, "inb : %04x %02x\n", addr, val); +#endif + return val; +} + +int cpu_inw(CPUState *env, int addr) +{ + int val; + val = ioport_read_table[1][addr](ioport_opaque[addr], addr); +#ifdef DEBUG_IOPORT + if (loglevel & CPU_LOG_IOPORT) + fprintf(logfile, "inw : %04x %04x\n", addr, val); +#endif + return val; +} + +int cpu_inl(CPUState *env, int addr) +{ + int val; + val = ioport_read_table[2][addr](ioport_opaque[addr], addr); +#ifdef DEBUG_IOPORT + if (loglevel & CPU_LOG_IOPORT) + fprintf(logfile, "inl : %04x %08x\n", addr, val); +#endif + return val; +} + +/***********************************************************/ +void hw_error(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "qemu: hardware error: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + abort(); +} + +/***********************************************************/ +/* keyboard/mouse */ + +static QEMUPutKBDEvent *qemu_put_kbd_event; +static void *qemu_put_kbd_event_opaque; +static QEMUPutMouseEvent *qemu_put_mouse_event; +static void *qemu_put_mouse_event_opaque; + +void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) +{ + qemu_put_kbd_event_opaque = opaque; + qemu_put_kbd_event = func; +} + +void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque) +{ + qemu_put_mouse_event_opaque = opaque; + qemu_put_mouse_event = func; +} + +void kbd_put_keycode(int keycode) +{ + if (qemu_put_kbd_event) { + qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode); + } +} + +void kbd_mouse_event(int dx, int dy, int dz, int buttons_state) +{ + if (qemu_put_mouse_event) { + qemu_put_mouse_event(qemu_put_mouse_event_opaque, + dx, dy, dz, buttons_state); + } +} + +/***********************************************************/ +/* timers */ + +#if defined(__powerpc__) + +static inline uint32_t get_tbl(void) +{ + uint32_t tbl; + asm volatile("mftb %0" : "=r" (tbl)); + return tbl; +} + +static inline uint32_t get_tbu(void) +{ + uint32_t tbl; + asm volatile("mftbu %0" : "=r" (tbl)); + return tbl; +} + +int64_t cpu_get_real_ticks(void) +{ + uint32_t l, h, h1; + /* NOTE: we test if wrapping has occurred */ + do { + h = get_tbu(); + l = get_tbl(); + h1 = get_tbu(); + } while (h != h1); + return ((int64_t)h << 32) | l; +} + +#elif defined(__i386__) + +int64_t cpu_get_real_ticks(void) +{ + int64_t val; + asm volatile ("rdtsc" : "=A" (val)); + return val; +} + +#elif defined(__x86_64__) + +int64_t cpu_get_real_ticks(void) +{ + uint32_t low,high; + int64_t val; + asm volatile("rdtsc" : "=a" (low), "=d" (high)); + val = high; + val <<= 32; + val |= low; + return val; +} + +#else +#error unsupported CPU +#endif + +static int64_t cpu_ticks_offset; +static int cpu_ticks_enabled; +int64_t cpu_virt_tsc; + +static inline int64_t cpu_get_ticks(void) +{ + if (!cpu_ticks_enabled) { + return cpu_ticks_offset; + } else { + return cpu_get_real_ticks() + cpu_ticks_offset; + } + +} + +/* enable cpu_get_ticks() */ +void cpu_enable_ticks(void) +{ + if (!cpu_ticks_enabled) { + cpu_ticks_offset -= cpu_get_real_ticks(); + cpu_ticks_enabled = 1; + } +} + +/* disable cpu_get_ticks() : the clock is stopped. You must not call + cpu_get_ticks() after that. */ +void cpu_disable_ticks(void) +{ + if (cpu_ticks_enabled) { + cpu_ticks_offset = cpu_get_ticks(); + cpu_ticks_enabled = 0; + } +} + +static int64_t get_clock(void) +{ +#ifdef _WIN32 + struct _timeb tb; + _ftime(&tb); + return ((int64_t)tb.time * 1000 + (int64_t)tb.millitm) * 1000; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000000LL + tv.tv_usec; +#endif +} + +void cpu_calibrate_ticks(void) +{ + int64_t usec, ticks; + + usec = get_clock(); + ticks = cpu_get_real_ticks(); +#ifdef _WIN32 + Sleep(50); +#else + usleep(50 * 1000); +#endif + usec = get_clock() - usec; + ticks = cpu_get_real_ticks() - ticks; + ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec; +} + +/* compute with 96 bit intermediate result: (a*b)/c */ +uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) +{ + union { + uint64_t ll; + struct { +#ifdef WORDS_BIGENDIAN + uint32_t high, low; +#else + uint32_t low, high; +#endif + } l; + } u, res; + uint64_t rl, rh; + + u.ll = a; + rl = (uint64_t)u.l.low * (uint64_t)b; + rh = (uint64_t)u.l.high * (uint64_t)b; + rh += (rl >> 32); + res.l.high = rh / c; + res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c; + return res.ll; +} + +#define QEMU_TIMER_REALTIME 0 +#define QEMU_TIMER_VIRTUAL 1 + +struct QEMUClock { + int type; + /* XXX: add frequency */ +}; + +struct QEMUTimer { + QEMUClock *clock; + int64_t expire_time; + QEMUTimerCB *cb; + void *opaque; + struct QEMUTimer *next; +}; + +QEMUClock *rt_clock; +QEMUClock *vm_clock; + +static QEMUTimer *active_timers[2]; +#ifdef _WIN32 +static MMRESULT timerID; +#else +/* frequency of the times() clock tick */ +static int timer_freq; +#endif + +QEMUClock *qemu_new_clock(int type) +{ + QEMUClock *clock; + clock = qemu_mallocz(sizeof(QEMUClock)); + if (!clock) + return NULL; + clock->type = type; + return clock; +} + +QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque) +{ + QEMUTimer *ts; + + ts = qemu_mallocz(sizeof(QEMUTimer)); + ts->clock = clock; + ts->cb = cb; + ts->opaque = opaque; + return ts; +} + +void qemu_free_timer(QEMUTimer *ts) +{ + qemu_free(ts); +} + +/* stop a timer, but do not dealloc it */ +void qemu_del_timer(QEMUTimer *ts) +{ + QEMUTimer **pt, *t; + + /* NOTE: this code must be signal safe because + qemu_timer_expired() can be called from a signal. */ + pt = &active_timers[ts->clock->type]; + for(;;) { + t = *pt; + if (!t) + break; + if (t == ts) { + *pt = t->next; + break; + } + pt = &t->next; + } +} + +/* modify the current timer so that it will be fired when current_time + >= expire_time. The corresponding callback will be called. */ +void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time) +{ + QEMUTimer **pt, *t; + + qemu_del_timer(ts); + + /* add the timer in the sorted list */ + /* NOTE: this code must be signal safe because + qemu_timer_expired() can be called from a signal. */ + pt = &active_timers[ts->clock->type]; + for(;;) { + t = *pt; + if (!t) + break; + if (t->expire_time > expire_time) + break; + pt = &t->next; + } + ts->expire_time = expire_time; + ts->next = *pt; + *pt = ts; +} + +int qemu_timer_pending(QEMUTimer *ts) +{ + QEMUTimer *t; + for(t = active_timers[ts->clock->type]; t != NULL; t = t->next) { + if (t == ts) + return 1; + } + return 0; +} + +static inline int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time) +{ + if (!timer_head) + return 0; + return (timer_head->expire_time <= current_time); +} + +static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time) +{ + QEMUTimer *ts; + + for(;;) { + ts = *ptimer_head; + if (!ts || ts->expire_time > current_time) + break; + /* remove timer from the list before calling the callback */ + *ptimer_head = ts->next; + ts->next = NULL; + + /* run the callback (the timer list can be modified) */ + ts->cb(ts->opaque); + } +} + +int64_t qemu_get_clock(QEMUClock *clock) +{ + switch(clock->type) { + case QEMU_TIMER_REALTIME: +#ifdef _WIN32 + return GetTickCount(); +#else + { + struct tms tp; + + /* Note that using gettimeofday() is not a good solution + for timers because its value change when the date is + modified. */ + if (timer_freq == 100) { + return times(&tp) * 10; + } else { + return ((int64_t)times(&tp) * 1000) / timer_freq; + } + } +#endif + default: + case QEMU_TIMER_VIRTUAL: + return cpu_get_ticks(); + } +} + +/* save a timer */ +void qemu_put_timer(QEMUFile *f, QEMUTimer *ts) +{ + uint64_t expire_time; + + if (qemu_timer_pending(ts)) { + expire_time = ts->expire_time; + } else { + expire_time = -1; + } + qemu_put_be64(f, expire_time); +} + +void qemu_get_timer(QEMUFile *f, QEMUTimer *ts) +{ + uint64_t expire_time; + + expire_time = qemu_get_be64(f); + if (expire_time != -1) { + qemu_mod_timer(ts, expire_time); + } else { + qemu_del_timer(ts); + } +} + +static void init_timers(void) +{ + rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME); + vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL); + +#ifdef _WIN32 + { + int count=0; + timerID = timeSetEvent(10, // interval (ms) + 0, // resolution + host_alarm_handler, // function + (DWORD)&count, // user parameter + TIME_PERIODIC | TIME_CALLBACK_FUNCTION); + if( !timerID ) { + perror("failed timer alarm"); + exit(1); + } + } + pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000; +#else + { + /* get times() syscall frequency */ + timer_freq = sysconf(_SC_CLK_TCK); + +#ifndef TARGET_VMX + /* timer signal */ + sigfillset(&act.sa_mask); + act.sa_flags = 0; +#if defined (TARGET_I386) && defined(USE_CODE_COPY) + act.sa_flags |= SA_ONSTACK; +#endif + act.sa_handler = host_alarm_handler; + sigaction(SIGALRM, &act, NULL); + + itv.it_interval.tv_sec = 0; + itv.it_interval.tv_usec = 1000; + itv.it_value.tv_sec = 0; + itv.it_value.tv_usec = 10 * 1000; + setitimer(ITIMER_REAL, &itv, NULL); + /* we probe the tick duration of the kernel to inform the user if + the emulated kernel requested a too high timer frequency */ + getitimer(ITIMER_REAL, &itv); + +#if defined(__linux__) + if (itv.it_interval.tv_usec > 1000) { + /* try to use /dev/rtc to have a faster timer */ + if (start_rtc_timer() < 0) + goto use_itimer; + /* disable itimer */ + itv.it_interval.tv_sec = 0; + itv.it_interval.tv_usec = 0; + itv.it_value.tv_sec = 0; + itv.it_value.tv_usec = 0; + setitimer(ITIMER_REAL, &itv, NULL); + + /* use the RTC */ + sigaction(SIGIO, &act, NULL); + fcntl(rtc_fd, F_SETFL, O_ASYNC); + fcntl(rtc_fd, F_SETOWN, getpid()); + } else +#endif /* defined(__linux__) */ + { + use_itimer: + pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * + PIT_FREQ) / 1000000; + } +#endif /* TARGET_VMX */ + } +#endif +} + +void quit_timers(void) +{ +#ifdef _WIN32 + timeKillEvent(timerID); +#endif +} + +/***********************************************************/ +/* character device */ + +int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len) +{ + return s->chr_write(s, buf, len); +} + +void qemu_chr_printf(CharDriverState *s, const char *fmt, ...) +{ + char buf[4096]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + qemu_chr_write(s, buf, strlen(buf)); + va_end(ap); +} + +void qemu_chr_send_event(CharDriverState *s, int event) +{ + if (s->chr_send_event) + s->chr_send_event(s, event); +} + +void qemu_chr_add_read_handler(CharDriverState *s, + IOCanRWHandler *fd_can_read, + IOReadHandler *fd_read, void *opaque) +{ + s->chr_add_read_handler(s, fd_can_read, fd_read, opaque); +} + +void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event) +{ + s->chr_event = chr_event; +} + +static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len) +{ + return len; +} + +static void null_chr_add_read_handler(CharDriverState *chr, + IOCanRWHandler *fd_can_read, + IOReadHandler *fd_read, void *opaque) +{ +} + +CharDriverState *qemu_chr_open_null(void) +{ + CharDriverState *chr; + + chr = qemu_mallocz(sizeof(CharDriverState)); + if (!chr) + return NULL; + chr->chr_write = null_chr_write; + chr->chr_add_read_handler = null_chr_add_read_handler; + return chr; +} + +#ifndef _WIN32 + +typedef struct { + int fd_in, fd_out; + /* for nographic stdio only */ + IOCanRWHandler *fd_can_read; + IOReadHandler *fd_read; + void *fd_opaque; +} FDCharDriver; + +#define STDIO_MAX_CLIENTS 2 + +static int stdio_nb_clients; +static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS]; + +static int unix_write(int fd, const uint8_t *buf, int len1) +{ + int ret, len; + + len = len1; + while (len > 0) { + ret = write(fd, buf, len); + if (ret < 0) { + if (errno != EINTR && errno != EAGAIN) + return -1; + } else if (ret == 0) { + break; + } else { + buf += ret; + len -= ret; + } + } + return len1 - len; +} + +static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) +{ + FDCharDriver *s = chr->opaque; + return unix_write(s->fd_out, buf, len); +} + +static void fd_chr_add_read_handler(CharDriverState *chr, + IOCanRWHandler *fd_can_read, + IOReadHandler *fd_read, void *opaque) +{ + FDCharDriver *s = chr->opaque; + + if (nographic && s->fd_in == 0) { + s->fd_can_read = fd_can_read; + s->fd_read = fd_read; + s->fd_opaque = opaque; + } else { + qemu_add_fd_read_handler(s->fd_in, fd_can_read, fd_read, opaque); + } +} + +/* open a character device to a unix fd */ +CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out) +{ + CharDriverState *chr; + FDCharDriver *s; + + chr = qemu_mallocz(sizeof(CharDriverState)); + if (!chr) + return NULL; + s = qemu_mallocz(sizeof(FDCharDriver)); + if (!s) { + free(chr); + return NULL; + } + s->fd_in = fd_in; + s->fd_out = fd_out; + chr->opaque = s; + chr->chr_write = fd_chr_write; + chr->chr_add_read_handler = fd_chr_add_read_handler; + return chr; +} + +/* for STDIO, we handle the case where several clients use it + (nographic mode) */ + +#define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */ + +static int term_got_escape, client_index; + +void term_print_help(void) +{ + printf("\n" + "C-a h print this help\n" + "C-a x exit emulator\n" + "C-a s save disk data back to file (if -snapshot)\n" + "C-a b send break (magic sysrq)\n" + "C-a c switch between console and monitor\n" + "C-a C-a send C-a\n" + ); +} + +/* called when a char is received */ +static void stdio_received_byte(int ch) +{ + if (term_got_escape) { + term_got_escape = 0; + switch(ch) { + case 'h': + term_print_help(); + break; + case 'x': + exit(0); + break; + case 's': + { + int i; + for (i = 0; i < MAX_DISKS; i++) { + if (bs_table[i]) + bdrv_commit(bs_table[i]); + } + } + break; + case 'b': + if (client_index < stdio_nb_clients) { + CharDriverState *chr; + FDCharDriver *s; + + chr = stdio_clients[client_index]; + s = chr->opaque; + chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK); + } + break; + case 'c': + client_index++; + if (client_index >= stdio_nb_clients) + client_index = 0; + if (client_index == 0) { + /* send a new line in the monitor to get the prompt */ + ch = '\r'; + goto send_char; + } + break; + case TERM_ESCAPE: + goto send_char; + } + } else if (ch == TERM_ESCAPE) { + term_got_escape = 1; + } else { + send_char: + if (client_index < stdio_nb_clients) { + uint8_t buf[1]; + CharDriverState *chr; + FDCharDriver *s; + + chr = stdio_clients[client_index]; + s = chr->opaque; + buf[0] = ch; + /* XXX: should queue the char if the device is not + ready */ + if (s->fd_can_read(s->fd_opaque) > 0) + s->fd_read(s->fd_opaque, buf, 1); + } + } +} + +static int stdio_can_read(void *opaque) +{ + /* XXX: not strictly correct */ + return 1; +} + +static void stdio_read(void *opaque, const uint8_t *buf, int size) +{ + int i; + for(i = 0; i < size; i++) + stdio_received_byte(buf[i]); +} + +/* init terminal so that we can grab keys */ +static struct termios oldtty; +static int old_fd0_flags; + +static void term_exit(void) +{ + tcsetattr (0, TCSANOW, &oldtty); + fcntl(0, F_SETFL, old_fd0_flags); +} + +static void term_init(void) +{ + struct termios tty; + + tcgetattr (0, &tty); + oldtty = tty; + old_fd0_flags = fcntl(0, F_GETFL); + + tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP + |INLCR|IGNCR|ICRNL|IXON); + tty.c_oflag |= OPOST; + tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN); + /* if graphical mode, we allow Ctrl-C handling */ + if (nographic) + tty.c_lflag &= ~ISIG; + tty.c_cflag &= ~(CSIZE|PARENB); + tty.c_cflag |= CS8; + tty.c_cc[VMIN] = 1; + tty.c_cc[VTIME] = 0; + + tcsetattr (0, TCSANOW, &tty); + + atexit(term_exit); + + fcntl(0, F_SETFL, O_NONBLOCK); +} + +CharDriverState *qemu_chr_open_stdio(void) +{ + CharDriverState *chr; + + if (nographic) { + if (stdio_nb_clients >= STDIO_MAX_CLIENTS) + return NULL; + chr = qemu_chr_open_fd(0, 1); + if (stdio_nb_clients == 0) + qemu_add_fd_read_handler(0, stdio_can_read, stdio_read, NULL); + client_index = stdio_nb_clients; + } else { + if (stdio_nb_clients != 0) + return NULL; + chr = qemu_chr_open_fd(0, 1); + } + stdio_clients[stdio_nb_clients++] = chr; + if (stdio_nb_clients == 1) { + /* set the terminal in raw mode */ + term_init(); + } + return chr; +} + +#if defined(__linux__) +CharDriverState *qemu_chr_open_pty(void) +{ + char slave_name[1024]; + int master_fd, slave_fd; + + /* Not satisfying */ + if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) { + return NULL; + } + fprintf(stderr, "char device redirected to %s\n", slave_name); + return qemu_chr_open_fd(master_fd, master_fd); +} +#else +CharDriverState *qemu_chr_open_pty(void) +{ + return NULL; +} +#endif + +#endif /* !defined(_WIN32) */ + +CharDriverState *qemu_chr_open(const char *filename) +{ + if (!strcmp(filename, "vc")) { + return text_console_init(&display_state); + } else if (!strcmp(filename, "null")) { + return qemu_chr_open_null(); + } else +#ifndef _WIN32 + if (!strcmp(filename, "pty")) { + return qemu_chr_open_pty(); + } else if (!strcmp(filename, "stdio")) { + return qemu_chr_open_stdio(); + } else +#endif + { + return NULL; + } +} + +/***********************************************************/ +/* Linux network device redirectors */ + +void hex_dump(FILE *f, const uint8_t *buf, int size) +{ + int len, i, j, c; + + for(i=0;i 16) + len = 16; + fprintf(f, "%08x ", i); + for(j=0;j<16;j++) { + if (j < len) + fprintf(f, " %02x", buf[i+j]); + else + fprintf(f, " "); + } + fprintf(f, " "); + for(j=0;j '~') + c = '.'; + fprintf(f, "%c", c); + } + fprintf(f, "\n"); + } +} + +void qemu_send_packet(NetDriverState *nd, const uint8_t *buf, int size) +{ + nd->send_packet(nd, buf, size); +} + +void qemu_add_read_packet(NetDriverState *nd, IOCanRWHandler *fd_can_read, + IOReadHandler *fd_read, void *opaque) +{ + nd->add_read_packet(nd, fd_can_read, fd_read, opaque); +} + +/* dummy network adapter */ + +static void dummy_send_packet(NetDriverState *nd, const uint8_t *buf, int size) +{ +} + +static void dummy_add_read_packet(NetDriverState *nd, + IOCanRWHandler *fd_can_read, + IOReadHandler *fd_read, void *opaque) +{ +} + +static int net_dummy_init(NetDriverState *nd) +{ + nd->send_packet = dummy_send_packet; + nd->add_read_packet = dummy_add_read_packet; + pstrcpy(nd->ifname, sizeof(nd->ifname), "dummy"); + return 0; +} + +#if defined(CONFIG_SLIRP) + +/* slirp network adapter */ + +static void *slirp_fd_opaque; +static IOCanRWHandler *slirp_fd_can_read; +static IOReadHandler *slirp_fd_read; +static int slirp_inited; + +int slirp_can_output(void) +{ + return slirp_fd_can_read(slirp_fd_opaque); +} + +void slirp_output(const uint8_t *pkt, int pkt_len) +{ +#if 0 + printf("output:\n"); + hex_dump(stdout, pkt, pkt_len); +#endif + slirp_fd_read(slirp_fd_opaque, pkt, pkt_len); +} + +static void slirp_send_packet(NetDriverState *nd, const uint8_t *buf, int size) +{ +#if 0 + printf("input:\n"); + hex_dump(stdout, buf, size); +#endif + slirp_input(buf, size); +} + +static void slirp_add_read_packet(NetDriverState *nd, + IOCanRWHandler *fd_can_read, + IOReadHandler *fd_read, void *opaque) +{ + slirp_fd_opaque = opaque; + slirp_fd_can_read = fd_can_read; + slirp_fd_read = fd_read; +} + +static int net_slirp_init(NetDriverState *nd) +{ + if (!slirp_inited) { + slirp_inited = 1; + slirp_init(); + } + nd->send_packet = slirp_send_packet; + nd->add_read_packet = slirp_add_read_packet; + pstrcpy(nd->ifname, sizeof(nd->ifname), "slirp"); + return 0; +} + +static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) +{ + const char *p, *p1; + int len; + p = *pp; + p1 = strchr(p, sep); + if (!p1) + return -1; + len = p1 - p; + p1++; + if (buf_size > 0) { + if (len > buf_size - 1) + len = buf_size - 1; + memcpy(buf, p, len); + buf[len] = '\0'; + } + *pp = p1; + return 0; +} + +static void net_slirp_redir(const char *redir_str) +{ + int is_udp; + char buf[256], *r; + const char *p; + struct in_addr guest_addr; + int host_port, guest_port; + + if (!slirp_inited) { + slirp_inited = 1; + slirp_init(); + } + + p = redir_str; + if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) + goto fail; + if (!strcmp(buf, "tcp")) { + is_udp = 0; + } else if (!strcmp(buf, "udp")) { + is_udp = 1; + } else { + goto fail; + } + + if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) + goto fail; + host_port = strtol(buf, &r, 0); + if (r == buf) + goto fail; + + if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) + goto fail; + if (buf[0] == '\0') { + pstrcpy(buf, sizeof(buf), "10.0.2.15"); + } + if (!inet_aton(buf, &guest_addr)) + goto fail; + + guest_port = strtol(p, &r, 0); + if (r == p) + goto fail; + + if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) { + fprintf(stderr, "qemu: could not set up redirection\n"); + exit(1); + } + return; + fail: + fprintf(stderr, "qemu: syntax: -redir [tcp|udp]:host-port:[guest-host]:guest-port\n"); + exit(1); +} + +#ifndef _WIN32 + +char smb_dir[1024]; + +static void smb_exit(void) +{ + DIR *d; + struct dirent *de; + char filename[1024]; + + /* erase all the files in the directory */ + d = opendir(smb_dir); + for(;;) { + de = readdir(d); + if (!de) + break; + if (strcmp(de->d_name, ".") != 0 && + strcmp(de->d_name, "..") != 0) { + snprintf(filename, sizeof(filename), "%s/%s", + smb_dir, de->d_name); + unlink(filename); + } + } + closedir(d); + rmdir(smb_dir); +} + +/* automatic user mode samba server configuration */ +void net_slirp_smb(const char *exported_dir) +{ + char smb_conf[1024]; + char smb_cmdline[1024]; + FILE *f; + + if (!slirp_inited) { + slirp_inited = 1; + slirp_init(); + } + + /* XXX: better tmp dir construction */ + snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%d", getpid()); + if (mkdir(smb_dir, 0700) < 0) { + fprintf(stderr, "qemu: could not create samba server dir '%s'\n", smb_dir); + exit(1); + } + snprintf(smb_conf, sizeof(smb_conf), "%s/%s", smb_dir, "smb.conf"); + + f = fopen(smb_conf, "w"); + if (!f) { + fprintf(stderr, "qemu: could not create samba server configuration file '%s'\n", smb_conf); + exit(1); + } + fprintf(f, + "[global]\n" + "pid directory=%s\n" + "lock directory=%s\n" + "log file=%s/log.smbd\n" + "smb passwd file=%s/smbpasswd\n" + "security = share\n" + "[qemu]\n" + "path=%s\n" + "read only=no\n" + "guest ok=yes\n", + smb_dir, + smb_dir, + smb_dir, + smb_dir, + exported_dir + ); + fclose(f); + atexit(smb_exit); + + snprintf(smb_cmdline, sizeof(smb_cmdline), "/usr/sbin/smbd -s %s", + smb_conf); + + slirp_add_exec(0, smb_cmdline, 4, 139); +} + +#endif /* !defined(_WIN32) */ + +#endif /* CONFIG_SLIRP */ + +#if !defined(_WIN32) +#ifdef _BSD +static int tun_open(char *ifname, int ifname_size) +{ + int fd; + char *dev; + struct stat s; + + fd = open("/dev/tap", O_RDWR); + if (fd < 0) { + fprintf(stderr, "warning: could not open /dev/tap: no virtual network emulation\n"); + return -1; + } + + fstat(fd, &s); + dev = devname(s.st_rdev, S_IFCHR); + pstrcpy(ifname, ifname_size, dev); + + fcntl(fd, F_SETFL, O_NONBLOCK); + return fd; +} +#else +static int tun_open(char *ifname, int ifname_size) +{ + struct ifreq ifr; + int fd, ret; + + fd = open("/dev/net/tun", O_RDWR); + if (fd < 0) { + fprintf(stderr, "warning: could not open /dev/net/tun: no virtual network emulation\n"); + return -1; + } + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = IFF_TAP | IFF_NO_PI; + pstrcpy(ifr.ifr_name, IFNAMSIZ, "tun%d"); + ret = ioctl(fd, TUNSETIFF, (void *) &ifr); + if (ret != 0) { + fprintf(stderr, "warning: could not configure /dev/net/tun: no virtual network emulation\n"); + close(fd); + return -1; + } + printf("Connected to host network interface: %s\n", ifr.ifr_name); + pstrcpy(ifname, ifname_size, ifr.ifr_name); + fcntl(fd, F_SETFL, O_NONBLOCK); + return fd; +} +#endif + +static void tun_send_packet(NetDriverState *nd, const uint8_t *buf, int size) +{ + write(nd->fd, buf, size); +} + +static void tun_add_read_packet(NetDriverState *nd, + IOCanRWHandler *fd_can_read, + IOReadHandler *fd_read, void *opaque) +{ + qemu_add_fd_read_handler(nd->fd, fd_can_read, fd_read, opaque); +} + +static int net_tun_init(NetDriverState *nd) +{ + int pid, status; + char *args[3]; + char **parg; + + nd->fd = tun_open(nd->ifname, sizeof(nd->ifname)); + if (nd->fd < 0) + return -1; + + /* try to launch network init script */ + pid = fork(); + if (pid >= 0) { + if (pid == 0) { + parg = args; + *parg++ = network_script; + *parg++ = nd->ifname; + *parg++ = NULL; + execv(network_script, args); + exit(1); + } + while (waitpid(pid, &status, 0) != pid); + if (!WIFEXITED(status) || + WEXITSTATUS(status) != 0) { + fprintf(stderr, "%s: could not launch network script\n", + network_script); + } + } + nd->send_packet = tun_send_packet; + nd->add_read_packet = tun_add_read_packet; + return 0; +} + +static int net_fd_init(NetDriverState *nd, int fd) +{ + nd->fd = fd; + nd->send_packet = tun_send_packet; + nd->add_read_packet = tun_add_read_packet; + pstrcpy(nd->ifname, sizeof(nd->ifname), "tunfd"); + return 0; +} + +#endif /* !_WIN32 */ + +/***********************************************************/ +/* dumb display */ + +static void dumb_update(DisplayState *ds, int x, int y, int w, int h) +{ +} + +static void dumb_resize(DisplayState *ds, int w, int h) +{ +} + +static void dumb_refresh(DisplayState *ds) +{ + vga_update_display(); +} + +void dumb_display_init(DisplayState *ds) +{ + ds->data = NULL; + ds->linesize = 0; + ds->depth = 0; + ds->dpy_update = dumb_update; + ds->dpy_resize = dumb_resize; + ds->dpy_refresh = dumb_refresh; +} + +#if !defined(CONFIG_SOFTMMU) +/***********************************************************/ +/* cpu signal handler */ +static void host_segv_handler(int host_signum, siginfo_t *info, + void *puc) +{ + abort(); +} +#endif + +/***********************************************************/ +/* I/O handling */ + +#define MAX_IO_HANDLERS 64 + +typedef struct IOHandlerRecord { + int fd; + IOCanRWHandler *fd_can_read; + IOReadHandler *fd_read; + void *opaque; + /* temporary data */ + struct pollfd *ufd; + int max_size; + struct IOHandlerRecord *next; +} IOHandlerRecord; + +static IOHandlerRecord *first_io_handler; + +int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read, + IOReadHandler *fd_read, void *opaque) +{ + IOHandlerRecord *ioh; + + ioh = qemu_mallocz(sizeof(IOHandlerRecord)); + if (!ioh) + return -1; + ioh->fd = fd; + ioh->fd_can_read = fd_can_read; + ioh->fd_read = fd_read; + ioh->opaque = opaque; + ioh->next = first_io_handler; + first_io_handler = ioh; + return 0; +} + +void qemu_del_fd_read_handler(int fd) +{ + IOHandlerRecord **pioh, *ioh; + + pioh = &first_io_handler; + for(;;) { + ioh = *pioh; + if (ioh == NULL) + break; + if (ioh->fd == fd) { + *pioh = ioh->next; + break; + } + pioh = &ioh->next; + } +} + +/***********************************************************/ +/* savevm/loadvm support */ + +void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) +{ + fwrite(buf, 1, size, f); +} + +void qemu_put_byte(QEMUFile *f, int v) +{ + fputc(v, f); +} + +void qemu_put_be16(QEMUFile *f, unsigned int v) +{ + qemu_put_byte(f, v >> 8); + qemu_put_byte(f, v); +} + +void qemu_put_be32(QEMUFile *f, unsigned int v) +{ + qemu_put_byte(f, v >> 24); + qemu_put_byte(f, v >> 16); + qemu_put_byte(f, v >> 8); + qemu_put_byte(f, v); +} + +void qemu_put_be64(QEMUFile *f, uint64_t v) +{ + qemu_put_be32(f, v >> 32); + qemu_put_be32(f, v); +} + +int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size) +{ + return fread(buf, 1, size, f); +} + +int qemu_get_byte(QEMUFile *f) +{ + int v; + v = fgetc(f); + if (v == EOF) + return 0; + else + return v; +} + +unsigned int qemu_get_be16(QEMUFile *f) +{ + unsigned int v; + v = qemu_get_byte(f) << 8; + v |= qemu_get_byte(f); + return v; +} + +unsigned int qemu_get_be32(QEMUFile *f) +{ + unsigned int v; + v = qemu_get_byte(f) << 24; + v |= qemu_get_byte(f) << 16; + v |= qemu_get_byte(f) << 8; + v |= qemu_get_byte(f); + return v; +} + +uint64_t qemu_get_be64(QEMUFile *f) +{ + uint64_t v; + v = (uint64_t)qemu_get_be32(f) << 32; + v |= qemu_get_be32(f); + return v; +} + +int64_t qemu_ftell(QEMUFile *f) +{ + return ftell(f); +} + +int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence) +{ + if (fseek(f, pos, whence) < 0) + return -1; + return ftell(f); +} + +typedef struct SaveStateEntry { + char idstr[256]; + int instance_id; + int version_id; + SaveStateHandler *save_state; + LoadStateHandler *load_state; + void *opaque; + struct SaveStateEntry *next; +} SaveStateEntry; + +static SaveStateEntry *first_se; + +int register_savevm(const char *idstr, + int instance_id, + int version_id, + SaveStateHandler *save_state, + LoadStateHandler *load_state, + void *opaque) +{ + SaveStateEntry *se, **pse; + + se = qemu_malloc(sizeof(SaveStateEntry)); + if (!se) + return -1; + pstrcpy(se->idstr, sizeof(se->idstr), idstr); + se->instance_id = instance_id; + se->version_id = version_id; + se->save_state = save_state; + se->load_state = load_state; + se->opaque = opaque; + se->next = NULL; + + /* add at the end of list */ + pse = &first_se; + while (*pse != NULL) + pse = &(*pse)->next; + *pse = se; + return 0; +} + +#define QEMU_VM_FILE_MAGIC 0x5145564d +#define QEMU_VM_FILE_VERSION 0x00000001 + +int qemu_savevm(const char *filename) +{ + SaveStateEntry *se; + QEMUFile *f; + int len, len_pos, cur_pos, saved_vm_running, ret; + + saved_vm_running = vm_running; + vm_stop(0); + + f = fopen(filename, "wb"); + if (!f) { + ret = -1; + goto the_end; + } + + qemu_put_be32(f, QEMU_VM_FILE_MAGIC); + qemu_put_be32(f, QEMU_VM_FILE_VERSION); + + for(se = first_se; se != NULL; se = se->next) { + /* ID string */ + len = strlen(se->idstr); + qemu_put_byte(f, len); + qemu_put_buffer(f, se->idstr, len); + + qemu_put_be32(f, se->instance_id); + qemu_put_be32(f, se->version_id); + + /* record size: filled later */ + len_pos = ftell(f); + qemu_put_be32(f, 0); + + se->save_state(f, se->opaque); + + /* fill record size */ + cur_pos = ftell(f); + len = ftell(f) - len_pos - 4; + fseek(f, len_pos, SEEK_SET); + qemu_put_be32(f, len); + fseek(f, cur_pos, SEEK_SET); + } + + fclose(f); + ret = 0; + the_end: + if (saved_vm_running) + vm_start(); + return ret; +} + +static SaveStateEntry *find_se(const char *idstr, int instance_id) +{ + SaveStateEntry *se; + + for(se = first_se; se != NULL; se = se->next) { + if (!strcmp(se->idstr, idstr) && + instance_id == se->instance_id) + return se; + } + return NULL; +} + +int qemu_loadvm(const char *filename) +{ + SaveStateEntry *se; + QEMUFile *f; + int len, cur_pos, ret, instance_id, record_len, version_id; + int saved_vm_running; + unsigned int v; + char idstr[256]; + + saved_vm_running = vm_running; + vm_stop(0); + + f = fopen(filename, "rb"); + if (!f) { + ret = -1; + goto the_end; + } + + v = qemu_get_be32(f); + if (v != QEMU_VM_FILE_MAGIC) + goto fail; + v = qemu_get_be32(f); + if (v != QEMU_VM_FILE_VERSION) { + fail: + fclose(f); + ret = -1; + goto the_end; + } + for(;;) { +#if defined (DO_TB_FLUSH) + tb_flush(global_env); +#endif + len = qemu_get_byte(f); + if (feof(f)) + break; + qemu_get_buffer(f, idstr, len); + idstr[len] = '\0'; + instance_id = qemu_get_be32(f); + version_id = qemu_get_be32(f); + record_len = qemu_get_be32(f); +#if 0 + printf("idstr=%s instance=0x%x version=%d len=%d\n", + idstr, instance_id, version_id, record_len); +#endif + cur_pos = ftell(f); + se = find_se(idstr, instance_id); + if (!se) { + fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n", + instance_id, idstr); + } else { + ret = se->load_state(f, se->opaque, version_id); + if (ret < 0) { + fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n", + instance_id, idstr); + } + } + /* always seek to exact end of record */ + qemu_fseek(f, cur_pos + record_len, SEEK_SET); + } + fclose(f); + ret = 0; + the_end: + if (saved_vm_running) + vm_start(); + return ret; +} + +/***********************************************************/ +/* main execution loop */ + +void gui_update(void *opaque) +{ + display_state.dpy_refresh(&display_state); + qemu_mod_timer(gui_timer, GUI_REFRESH_INTERVAL + qemu_get_clock(rt_clock)); +} +void polling_handler(void *opaque) +{ +#ifndef _WIN32 + struct pollfd ufds[MAX_IO_HANDLERS + 1], *pf; + IOHandlerRecord *ioh, *ioh_next; + uint8_t buf[4096]; + int n, max_size; +#endif + int timeout = 0; + int ret; + +#ifdef _WIN32 + if (timeout > 0) + Sleep(timeout); +#else + /* poll any events */ + /* XXX: separate device handlers from system ones */ + pf = ufds; + for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { + if (!ioh->fd_can_read) { + max_size = 0; + pf->fd = ioh->fd; + pf->events = POLLIN; + ioh->ufd = pf; + pf++; + } else { + max_size = ioh->fd_can_read(ioh->opaque); + if (max_size > 0) { + if (max_size > sizeof(buf)) + max_size = sizeof(buf); + pf->fd = ioh->fd; + pf->events = POLLIN; + ioh->ufd = pf; + pf++; + } else { + ioh->ufd = NULL; + } + } + ioh->max_size = max_size; + } + + ret = poll(ufds, pf - ufds, timeout); + if (ret > 0) { + /* XXX: better handling of removal */ + for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) { + ioh_next = ioh->next; + pf = ioh->ufd; + if (pf) { + if (pf->revents & POLLIN) { + if (ioh->max_size == 0) { + /* just a read event */ + ioh->fd_read(ioh->opaque, NULL, 0); + } else { + n = read(ioh->fd, buf, ioh->max_size); + if (n >= 0) { + ioh->fd_read(ioh->opaque, buf, n); + } else if (errno != EAGAIN) { + ioh->fd_read(ioh->opaque, NULL, -errno); + } + } + } + } + } + } +#endif /* !defined(_WIN32) */ + + qemu_mod_timer(polling_timer, POLLING_INTERVAL + qemu_get_clock(rt_clock)); +} + + +/* XXX: support several handlers */ +VMStopHandler *vm_stop_cb; +VMStopHandler *vm_stop_opaque; + +int qemu_add_vm_stop_handler(VMStopHandler *cb, void *opaque) +{ + vm_stop_cb = cb; + vm_stop_opaque = opaque; + return 0; +} + +void qemu_del_vm_stop_handler(VMStopHandler *cb, void *opaque) +{ + vm_stop_cb = NULL; +} + +void vm_start(void) +{ + if (!vm_running) { + cpu_enable_ticks(); + vm_running = 1; + } +} + +void vm_stop(int reason) +{ + if (vm_running) { + cpu_disable_ticks(); + vm_running = 0; + if (reason != 0) { + if (vm_stop_cb) { + vm_stop_cb(vm_stop_opaque, reason); + } + } + } +} + +/* reset/shutdown handler */ + +typedef struct QEMUResetEntry { + QEMUResetHandler *func; + void *opaque; + struct QEMUResetEntry *next; +} QEMUResetEntry; + +static QEMUResetEntry *first_reset_entry; +static int reset_requested; +int shutdown_requested; + +void qemu_register_reset(QEMUResetHandler *func, void *opaque) +{ + QEMUResetEntry **pre, *re; + + pre = &first_reset_entry; + while (*pre != NULL) + pre = &(*pre)->next; + re = qemu_mallocz(sizeof(QEMUResetEntry)); + re->func = func; + re->opaque = opaque; + re->next = NULL; + *pre = re; +} + +void qemu_system_reset(void) +{ + QEMUResetEntry *re; + + /* reset all devices */ + for(re = first_reset_entry; re != NULL; re = re->next) { + re->func(re->opaque); + } +} + +void qemu_system_reset_request(void) +{ + reset_requested = 1; + cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); +} + +void qemu_system_shutdown_request(void) +{ + shutdown_requested = 1; + cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); +} + +void main_loop_wait(int timeout) +{ + if (vm_running) { + qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], + qemu_get_clock(vm_clock)); + /* run dma transfers, if any */ + DMA_run(); + } + + /* real time timers */ + qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME], + qemu_get_clock(rt_clock)); +} + +void help(void) +{ + printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n" + "usage: %s [options] [disk_image]\n" + "\n" + "'disk_image' is a raw hard image image for IDE hard disk 0\n" + "\n" + "Standard options:\n" + "-fda/-fdb file use 'file' as floppy disk 0/1 image\n" + "-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n" + "-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n" + "-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n" + "-boot [a|c|d] boot on floppy (a), hard disk (c) or CD-ROM (d)\n" + "-snapshot write to temporary files instead of disk image files\n" + "-m megs set virtual RAM size to megs MB [default=%d]\n" + "-nographic disable graphical output and redirect serial I/Os to console\n" +#ifdef CONFIG_VNC + "-vnc use vnc instead of sdl\n" +#ifdef CONFIG_SDL + "-vnc-and-sdl use vnc and sdl simultaneously\n" +#endif +#endif + "-k use keyboard layout (for example \"fr\" for french)\n" + "-enable-audio enable audio support\n" + "-localtime set the real time clock to local time [default=utc]\n" + "-full-screen start in full screen\n" +#ifdef TARGET_PPC + "-prep Simulate a PREP system (default is PowerMAC)\n" + "-g WxH[xDEPTH] Set the initial VGA graphic mode\n" +#endif + "\n" + "Network options:\n" + "-nics n simulate 'n' network cards [default=1]\n" + "-macaddr addr set the mac address of the first interface\n" + "-n script set tap/tun network init script [default=%s]\n" + "-tun-fd fd use this fd as already opened tap/tun interface\n" +#ifdef CONFIG_SLIRP + "-user-net use user mode network stack [default if no tap/tun script]\n" + "-tftp prefix allow tftp access to files starting with prefix [-user-net]\n" +#ifndef _WIN32 + "-smb dir allow SMB access to files in 'dir' [-user-net]\n" +#endif + "-redir [tcp|udp]:host-port:[guest-host]:guest-port\n" + " redirect TCP or UDP connections from host to guest [-user-net]\n" +#endif + "-dummy-net use dummy network stack\n" + "\n" + "Linux boot specific:\n" + "-kernel bzImage use 'bzImage' as kernel image\n" + "-append cmdline use 'cmdline' as kernel command line\n" + "-initrd file use 'file' as initial ram disk\n" + "\n" + "Debug/Expert options:\n" + "-monitor dev redirect the monitor to char device 'dev'\n" + "-serial dev redirect the serial port to char device 'dev'\n" + "-S freeze CPU at startup (use 'c' to start execution)\n" + "-s wait gdb connection to port %d\n" + "-p port ioreq port for xen\n" + "-d domain domain that we're serving\n" + "-hdachs c,h,s force hard disk 0 geometry (usually qemu can guess it)\n" + "-L path set the directory for the BIOS and VGA BIOS\n" +#ifdef USE_CODE_COPY + "-no-code-copy disable code copy acceleration\n" +#endif +#ifdef TARGET_I386 + "-isa simulate an ISA-only system (default is PCI system)\n" + "-std-vga simulate a standard VGA card with VESA Bochs Extensions\n" + " (default is CL-GD5446 PCI VGA)\n" +#endif + "-loadvm file start right away with a saved state (loadvm in monitor)\n" + "\n" + "During emulation, the following keys are useful:\n" + "ctrl-alt-f toggle full screen\n" + "ctrl-alt-n switch to virtual console 'n'\n" + "ctrl-alt toggle mouse and keyboard grab\n" + "\n" + "When using -nographic, press 'ctrl-a h' to get some help.\n" + , +#ifdef CONFIG_SOFTMMU + "qemu", +#else + "qemu-fast", +#endif + DEFAULT_RAM_SIZE, + DEFAULT_NETWORK_SCRIPT, + DEFAULT_GDBSTUB_PORT); +#ifndef CONFIG_SOFTMMU + printf("\n" + "NOTE: this version of QEMU is faster but it needs slightly patched OSes to\n" + "work. Please use the 'qemu' executable to have a more accurate (but slower)\n" + "PC emulation.\n"); +#endif + exit(1); +} + +#define HAS_ARG 0x0001 + +enum { + QEMU_OPTION_h, + + QEMU_OPTION_fda, + QEMU_OPTION_fdb, + QEMU_OPTION_hda, + QEMU_OPTION_hdb, + QEMU_OPTION_hdc, + QEMU_OPTION_hdd, + QEMU_OPTION_cdrom, + QEMU_OPTION_boot, + QEMU_OPTION_snapshot, + QEMU_OPTION_m, + QEMU_OPTION_nographic, +#ifdef CONFIG_VNC + QEMU_OPTION_vnc, +#ifdef CONFIG_SDL + QEMU_OPTION_vnc_and_sdl, +#endif +#endif + QEMU_OPTION_enable_audio, + + QEMU_OPTION_nics, + QEMU_OPTION_macaddr, + QEMU_OPTION_n, + QEMU_OPTION_tun_fd, + QEMU_OPTION_user_net, + QEMU_OPTION_tftp, + QEMU_OPTION_smb, + QEMU_OPTION_redir, + QEMU_OPTION_dummy_net, + + QEMU_OPTION_kernel, + QEMU_OPTION_append, + QEMU_OPTION_initrd, + + QEMU_OPTION_S, + QEMU_OPTION_s, + QEMU_OPTION_p, + QEMU_OPTION_d, + QEMU_OPTION_l, + QEMU_OPTION_hdachs, + QEMU_OPTION_L, + QEMU_OPTION_no_code_copy, + QEMU_OPTION_pci, + QEMU_OPTION_isa, + QEMU_OPTION_prep, + QEMU_OPTION_k, + QEMU_OPTION_localtime, + QEMU_OPTION_cirrusvga, + QEMU_OPTION_g, + QEMU_OPTION_std_vga, + QEMU_OPTION_monitor, + QEMU_OPTION_serial, + QEMU_OPTION_loadvm, + QEMU_OPTION_full_screen, +}; + +typedef struct QEMUOption { + const char *name; + int flags; + int index; +} QEMUOption; + +const QEMUOption qemu_options[] = { + { "h", 0, QEMU_OPTION_h }, + + { "fda", HAS_ARG, QEMU_OPTION_fda }, + { "fdb", HAS_ARG, QEMU_OPTION_fdb }, + { "hda", HAS_ARG, QEMU_OPTION_hda }, + { "hdb", HAS_ARG, QEMU_OPTION_hdb }, + { "hdc", HAS_ARG, QEMU_OPTION_hdc }, + { "hdd", HAS_ARG, QEMU_OPTION_hdd }, + { "cdrom", HAS_ARG, QEMU_OPTION_cdrom }, + { "boot", HAS_ARG, QEMU_OPTION_boot }, + { "snapshot", 0, QEMU_OPTION_snapshot }, + { "m", HAS_ARG, QEMU_OPTION_m }, + { "nographic", 0, QEMU_OPTION_nographic }, +#ifdef CONFIG_VNC + { "vnc", 0, QEMU_OPTION_vnc }, +#ifdef CONFIG_SDL + { "vnc-and-sdl", 0, QEMU_OPTION_vnc_and_sdl }, +#endif +#endif + { "k", HAS_ARG, QEMU_OPTION_k }, + { "enable-audio", 0, QEMU_OPTION_enable_audio }, + + { "nics", HAS_ARG, QEMU_OPTION_nics}, + { "macaddr", HAS_ARG, QEMU_OPTION_macaddr}, + { "n", HAS_ARG, QEMU_OPTION_n }, + { "tun-fd", HAS_ARG, QEMU_OPTION_tun_fd }, +#ifdef CONFIG_SLIRP + { "user-net", 0, QEMU_OPTION_user_net }, + { "tftp", HAS_ARG, QEMU_OPTION_tftp }, +#ifndef _WIN32 + { "smb", HAS_ARG, QEMU_OPTION_smb }, +#endif + { "redir", HAS_ARG, QEMU_OPTION_redir }, +#endif + { "dummy-net", 0, QEMU_OPTION_dummy_net }, + + { "kernel", HAS_ARG, QEMU_OPTION_kernel }, + { "append", HAS_ARG, QEMU_OPTION_append }, + { "initrd", HAS_ARG, QEMU_OPTION_initrd }, + + { "S", 0, QEMU_OPTION_S }, + { "s", 0, QEMU_OPTION_s }, + { "p", HAS_ARG, QEMU_OPTION_p }, + { "d", HAS_ARG, QEMU_OPTION_d }, + { "l", HAS_ARG, QEMU_OPTION_l }, + { "hdachs", HAS_ARG, QEMU_OPTION_hdachs }, + { "L", HAS_ARG, QEMU_OPTION_L }, + { "no-code-copy", 0, QEMU_OPTION_no_code_copy }, +#ifdef TARGET_PPC + { "prep", 0, QEMU_OPTION_prep }, + { "g", 1, QEMU_OPTION_g }, +#endif + { "localtime", 0, QEMU_OPTION_localtime }, + { "isa", 0, QEMU_OPTION_isa }, + { "std-vga", 0, QEMU_OPTION_std_vga }, + { "monitor", 1, QEMU_OPTION_monitor }, + { "serial", 1, QEMU_OPTION_serial }, + { "loadvm", HAS_ARG, QEMU_OPTION_loadvm }, + { "full-screen", 0, QEMU_OPTION_full_screen }, + + /* temporary options */ + { "pci", 0, QEMU_OPTION_pci }, + { "cirrusvga", 0, QEMU_OPTION_cirrusvga }, + { NULL }, +}; + +#if defined (TARGET_I386) && defined(USE_CODE_COPY) + +/* this stack is only used during signal handling */ +#define SIGNAL_STACK_SIZE 32768 + +static uint8_t *signal_stack; + +#endif + +#define NET_IF_TUN 0 +#define NET_IF_USER 1 +#define NET_IF_DUMMY 2 + +int main(int argc, char **argv) +{ +#ifdef CONFIG_GDBSTUB + int use_gdbstub, gdbstub_port; +#endif + int i, has_cdrom; + int snapshot, linux_boot; + CPUState *env; + const char *initrd_filename; + const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD]; + const char *kernel_filename, *kernel_cmdline; + DisplayState *ds = &display_state; + int cyls, heads, secs; + int start_emulation = 1; + uint8_t macaddr[6]; + int net_if_type, nb_tun_fds, tun_fds[MAX_NICS]; + int optind; + const char *r, *optarg; + CharDriverState *monitor_hd; + char monitor_device[128]; + char serial_devices[MAX_SERIAL_PORTS][128]; + int serial_device_index; + const char *loadvm = NULL; + unsigned long nr_pages, *page_array; + extern void *shared_page; + /* change the qemu-dm to daemon, just like bochs dm */ +// daemon(0, 0); + +#if !defined(CONFIG_SOFTMMU) + /* we never want that malloc() uses mmap() */ + mallopt(M_MMAP_THRESHOLD, 4096 * 1024); +#endif + initrd_filename = NULL; + for(i = 0; i < MAX_FD; i++) + fd_filename[i] = NULL; + for(i = 0; i < MAX_DISKS; i++) + hd_filename[i] = NULL; + ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; + vga_ram_size = VGA_RAM_SIZE; + bios_size = BIOS_SIZE; + pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT); +#ifdef CONFIG_GDBSTUB + use_gdbstub = 0; + gdbstub_port = DEFAULT_GDBSTUB_PORT; +#endif + snapshot = 0; + nographic = 0; + usevnc = 0; + kernel_filename = NULL; + kernel_cmdline = ""; + has_cdrom = 1; + cyls = heads = secs = 0; + pstrcpy(monitor_device, sizeof(monitor_device), "vc"); + + pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "vc"); + for(i = 1; i < MAX_SERIAL_PORTS; i++) + serial_devices[i][0] = '\0'; + serial_device_index = 0; + + nb_tun_fds = 0; + net_if_type = -1; + nb_nics = 1; + /* default mac address of the first network interface */ + macaddr[0] = 0x52; + macaddr[1] = 0x54; + macaddr[2] = 0x00; + macaddr[3] = 0x12; + macaddr[4] = 0x34; + macaddr[5] = 0x56; + + optind = 1; + for(;;) { + if (optind >= argc) + break; + r = argv[optind]; + if (r[0] != '-') { + hd_filename[0] = argv[optind++]; + } else { + const QEMUOption *popt; + + optind++; + popt = qemu_options; + for(;;) { + if (!popt->name) { + fprintf(stderr, "%s: invalid option -- '%s'\n", + argv[0], r); + exit(1); + } + if (!strcmp(popt->name, r + 1)) + break; + popt++; + } + if (popt->flags & HAS_ARG) { + if (optind >= argc) { + fprintf(stderr, "%s: option '%s' requires an argument\n", + argv[0], r); + exit(1); + } + optarg = argv[optind++]; + } else { + optarg = NULL; + } + + switch(popt->index) { + case QEMU_OPTION_initrd: + initrd_filename = optarg; + break; + case QEMU_OPTION_hda: + hd_filename[0] = optarg; + break; + case QEMU_OPTION_hdb: + hd_filename[1] = optarg; + break; + case QEMU_OPTION_snapshot: + snapshot = 1; + break; + case QEMU_OPTION_hdachs: + { + const char *p; + p = optarg; + cyls = strtol(p, (char **)&p, 0); + if (*p != ',') + goto chs_fail; + p++; + heads = strtol(p, (char **)&p, 0); + if (*p != ',') + goto chs_fail; + p++; + secs = strtol(p, (char **)&p, 0); + if (*p != '\0') { + chs_fail: + cyls = 0; + } + } + break; + case QEMU_OPTION_nographic: + pstrcpy(monitor_device, sizeof(monitor_device), "stdio"); + pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio"); + nographic = 1; + break; +#ifdef CONFIG_VNC + case QEMU_OPTION_vnc: + usevnc = 1; + break; +#ifdef CONFIG_SDL + case QEMU_OPTION_vnc_and_sdl: + usevnc = 2; + break; +#endif +#endif + case QEMU_OPTION_kernel: + kernel_filename = optarg; + break; + case QEMU_OPTION_append: + kernel_cmdline = optarg; + break; + case QEMU_OPTION_tun_fd: + { + const char *p; + int fd; + net_if_type = NET_IF_TUN; + if (nb_tun_fds < MAX_NICS) { + fd = strtol(optarg, (char **)&p, 0); + if (*p != '\0') { + fprintf(stderr, "qemu: invalid fd for network interface %d\n", nb_tun_fds); + exit(1); + } + tun_fds[nb_tun_fds++] = fd; + } + } + break; + case QEMU_OPTION_hdc: + hd_filename[2] = optarg; + has_cdrom = 0; + break; + case QEMU_OPTION_hdd: + hd_filename[3] = optarg; + break; + case QEMU_OPTION_cdrom: + hd_filename[2] = optarg; + has_cdrom = 1; + break; + case QEMU_OPTION_boot: + boot_device = optarg[0]; + if (boot_device != 'a' && + boot_device != 'c' && boot_device != 'd') { + fprintf(stderr, "qemu: invalid boot device '%c'\n", boot_device); + exit(1); + } + break; + case QEMU_OPTION_fda: + fd_filename[0] = optarg; + break; + case QEMU_OPTION_fdb: + fd_filename[1] = optarg; + break; + case QEMU_OPTION_nics: + nb_nics = atoi(optarg); + if (nb_nics < 0 || nb_nics > MAX_NICS) { + fprintf(stderr, "qemu: invalid number of network interfaces\n"); + exit(1); + } + break; + case QEMU_OPTION_macaddr: + { + const char *p; + int i; + p = optarg; + for(i = 0; i < 6; i++) { + macaddr[i] = strtol(p, (char **)&p, 16); + if (i == 5) { + if (*p != '\0') + goto macaddr_error; + } else { + if (*p != ':') { + macaddr_error: + fprintf(stderr, "qemu: invalid syntax for ethernet address\n"); + exit(1); + } + p++; + } + } + } + break; +#ifdef CONFIG_SLIRP + case QEMU_OPTION_tftp: + tftp_prefix = optarg; + break; +#ifndef _WIN32 + case QEMU_OPTION_smb: + net_slirp_smb(optarg); + break; +#endif + case QEMU_OPTION_user_net: + net_if_type = NET_IF_USER; + break; + case QEMU_OPTION_redir: + net_slirp_redir(optarg); + break; +#endif + case QEMU_OPTION_dummy_net: + net_if_type = NET_IF_DUMMY; + break; + case QEMU_OPTION_enable_audio: + audio_enabled = 1; + break; + case QEMU_OPTION_h: + help(); + break; + case QEMU_OPTION_m: + ram_size = atoi(optarg) * 1024 * 1024; + if (ram_size <= 0) + help(); + break; + case QEMU_OPTION_d: + { + domid = atoi(optarg); + printf("domid: %d\n", domid); + } + break; + + case QEMU_OPTION_p: + { + extern short ioreq_port; + ioreq_port = atoi(optarg); + printf("port: %d\n", ioreq_port); + } + break; + case QEMU_OPTION_l: + { + int mask; + mask = cpu_str_to_log_mask(optarg); + printf("mask: %x\n", mask); + cpu_set_log(mask); + } + break; + case QEMU_OPTION_n: + pstrcpy(network_script, sizeof(network_script), optarg); + break; +#ifdef CONFIG_GDBSTUB + case QEMU_OPTION_s: + use_gdbstub = 1; + break; +#endif + case QEMU_OPTION_L: + bios_dir = optarg; + break; + case QEMU_OPTION_S: + start_emulation = 0; + break; + case QEMU_OPTION_pci: + pci_enabled = 1; + break; + case QEMU_OPTION_isa: + pci_enabled = 0; + break; + case QEMU_OPTION_prep: + prep_enabled = 1; + break; + case QEMU_OPTION_k: + keyboard_layout = optarg; + break; + case QEMU_OPTION_localtime: + rtc_utc = 0; + break; + case QEMU_OPTION_cirrusvga: + cirrus_vga_enabled = 1; + break; + case QEMU_OPTION_std_vga: + cirrus_vga_enabled = 0; + break; + case QEMU_OPTION_g: + { + const char *p; + int w, h, depth; + p = optarg; + w = strtol(p, (char **)&p, 10); + if (w <= 0) { + graphic_error: + fprintf(stderr, "qemu: invalid resolution or depth\n"); + exit(1); + } + if (*p != 'x') + goto graphic_error; + p++; + h = strtol(p, (char **)&p, 10); + if (h <= 0) + goto graphic_error; + if (*p == 'x') { + p++; + depth = strtol(p, (char **)&p, 10); + if (depth != 8 && depth != 15 && depth != 16 && + depth != 24 && depth != 32) + goto graphic_error; + } else if (*p == '\0') { + depth = graphic_depth; + } else { + goto graphic_error; + } + + graphic_width = w; + graphic_height = h; + graphic_depth = depth; + } + break; + case QEMU_OPTION_monitor: + pstrcpy(monitor_device, sizeof(monitor_device), optarg); + break; + case QEMU_OPTION_serial: + if (serial_device_index >= MAX_SERIAL_PORTS) { + fprintf(stderr, "qemu: too many serial ports\n"); + exit(1); + } + pstrcpy(serial_devices[serial_device_index], + sizeof(serial_devices[0]), optarg); + serial_device_index++; + break; + case QEMU_OPTION_loadvm: + loadvm = optarg; + break; + case QEMU_OPTION_full_screen: + full_screen = 1; + break; + } + } + } + + linux_boot = (kernel_filename != NULL); + + if (!linux_boot && hd_filename[0] == '\0' && hd_filename[2] == '\0' && + fd_filename[0] == '\0') + help(); + + /* boot to cd by default if no hard disk */ + if (hd_filename[0] == '\0' && boot_device == 'c') { + if (fd_filename[0] != '\0') + boot_device = 'a'; + else + boot_device = 'd'; + } + +#if !defined(CONFIG_SOFTMMU) + /* must avoid mmap() usage of glibc by setting a buffer "by hand" */ + { + static uint8_t stdout_buf[4096]; + setvbuf(stdout, stdout_buf, _IOLBF, sizeof(stdout_buf)); + } +#else + setvbuf(stdout, NULL, _IOLBF, 0); +#endif + + /* init host network redirectors */ + if (net_if_type == -1) { + net_if_type = NET_IF_TUN; +#if defined(CONFIG_SLIRP) + if (access(network_script, R_OK) < 0) { + net_if_type = NET_IF_USER; + } +#endif + } + + for(i = 0; i < nb_nics; i++) { + NetDriverState *nd = &nd_table[i]; + nd->index = i; + /* init virtual mac address */ + nd->macaddr[0] = macaddr[0]; + nd->macaddr[1] = macaddr[1]; + nd->macaddr[2] = macaddr[2]; + nd->macaddr[3] = macaddr[3]; + nd->macaddr[4] = macaddr[4]; + nd->macaddr[5] = macaddr[5] + i; + switch(net_if_type) { +#if defined(CONFIG_SLIRP) + case NET_IF_USER: + net_slirp_init(nd); + break; +#endif +#if !defined(_WIN32) + case NET_IF_TUN: + if (i < nb_tun_fds) { + net_fd_init(nd, tun_fds[i]); + } else { + if (net_tun_init(nd) < 0) + net_dummy_init(nd); + } + break; +#endif + case NET_IF_DUMMY: + default: + net_dummy_init(nd); + break; + } + } + + /* init the memory */ + phys_ram_size = ram_size + vga_ram_size + bios_size; + + #define PAGE_SHIFT 12 + #define PAGE_SIZE (1 << PAGE_SHIFT) + + nr_pages = ram_size/PAGE_SIZE; + xc_handle = xc_interface_open(); + + if ( (page_array = (unsigned long *) + malloc(nr_pages * sizeof(unsigned long))) == NULL) + { + perror("malloc"); + exit(-1); + } + + if ( xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages ) + { + perror("xc_get_pfn_list"); + exit(-1); + } + + if ((phys_ram_base = xc_map_foreign_batch(xc_handle, domid, + PROT_READ|PROT_WRITE, + page_array, + nr_pages - 1)) == 0) { + perror("xc_map_foreign_batch"); + exit(-1); + } + + + shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE, + PROT_READ|PROT_WRITE, + page_array[nr_pages - 1]); + + /* we always create the cdrom drive, even if no disk is there */ + bdrv_init(); + if (has_cdrom) { + bs_table[2] = bdrv_new("cdrom"); + bdrv_set_type_hint(bs_table[2], BDRV_TYPE_CDROM); + } + + /* open the virtual block devices */ + for(i = 0; i < MAX_DISKS; i++) { + if (hd_filename[i]) { + if (!bs_table[i]) { + char buf[64]; + snprintf(buf, sizeof(buf), "hd%c", i + 'a'); + bs_table[i] = bdrv_new(buf); + } + if (bdrv_open(bs_table[i], hd_filename[i], snapshot) < 0) { + fprintf(stderr, "qemu: could not open hard disk image '%s'\n", + hd_filename[i]); + exit(1); + } + if (i == 0 && cyls != 0) + bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs); + } + } + + /* we always create at least one floppy disk */ + fd_table[0] = bdrv_new("fda"); + bdrv_set_type_hint(fd_table[0], BDRV_TYPE_FLOPPY); + + for(i = 0; i < MAX_FD; i++) { + if (fd_filename[i]) { + if (!fd_table[i]) { + char buf[64]; + snprintf(buf, sizeof(buf), "fd%c", i + 'a'); + fd_table[i] = bdrv_new(buf); + bdrv_set_type_hint(fd_table[i], BDRV_TYPE_FLOPPY); + } + if (fd_filename[i] != '\0') { + if (bdrv_open(fd_table[i], fd_filename[i], snapshot) < 0) { + fprintf(stderr, "qemu: could not open floppy disk image '%s'\n", + fd_filename[i]); + exit(1); + } + } + } + } + + /* init CPU state */ + env = cpu_init(); + global_env = env; + cpu_single_env = env; + + init_ioports(); + cpu_calibrate_ticks(); + + /* terminal init */ + if (nographic) { + dumb_display_init(ds); + } else { + if (usevnc) { +#ifdef CONFIG_VNC + vnc_display_init(ds, (usevnc==2)); +#else + perror("qemu not configured with vnc support"); +#endif + } else { +#ifdef CONFIG_SDL + sdl_display_init(ds, full_screen); +#else + dumb_display_init(ds); +#endif + } + } + + vga_console = graphic_console_init(ds); + + monitor_hd = qemu_chr_open(monitor_device); + if (!monitor_hd) { + fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device); + exit(1); + } + monitor_init(monitor_hd, !nographic); + + for(i = 0; i < MAX_SERIAL_PORTS; i++) { + if (serial_devices[i][0] != '\0') { + serial_hds[i] = qemu_chr_open(serial_devices[i]); + if (!serial_hds[i]) { + fprintf(stderr, "qemu: could not open serial device '%s'\n", + serial_devices[i]); + exit(1); + } + if (!strcmp(serial_devices[i], "vc")) + qemu_chr_printf(serial_hds[i], "serial%d console\n", i); + } + } + + /* setup cpu signal handlers for MMU / self modifying code handling */ +#if !defined(CONFIG_SOFTMMU) + +#if defined (TARGET_I386) && defined(USE_CODE_COPY) + { + stack_t stk; + signal_stack = memalign(16, SIGNAL_STACK_SIZE); + stk.ss_sp = signal_stack; + stk.ss_size = SIGNAL_STACK_SIZE; + stk.ss_flags = 0; + + if (sigaltstack(&stk, NULL) < 0) { + perror("sigaltstack"); + exit(1); + } + } +#endif + { + struct sigaction act; + + sigfillset(&act.sa_mask); + act.sa_flags = SA_SIGINFO; +#if defined (TARGET_I386) && defined(USE_CODE_COPY) + act.sa_flags |= SA_ONSTACK; +#endif + act.sa_sigaction = host_segv_handler; + sigaction(SIGSEGV, &act, NULL); + sigaction(SIGBUS, &act, NULL); +#if defined (TARGET_I386) && defined(USE_CODE_COPY) + sigaction(SIGFPE, &act, NULL); +#endif + } +#endif + +#ifndef _WIN32 + { + struct sigaction act; + sigfillset(&act.sa_mask); + act.sa_flags = 0; + act.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &act, NULL); + } +#endif + init_timers(); + +#if defined(TARGET_I386) + pc_init(ram_size, vga_ram_size, boot_device, + ds, fd_filename, snapshot, + kernel_filename, kernel_cmdline, initrd_filename); +#elif defined(TARGET_PPC) + ppc_init(ram_size, vga_ram_size, boot_device, + ds, fd_filename, snapshot, + kernel_filename, kernel_cmdline, initrd_filename); +#elif defined(TARGET_SPARC) + sun4m_init(ram_size, vga_ram_size, boot_device, + ds, fd_filename, snapshot, + kernel_filename, kernel_cmdline, initrd_filename); +#endif + + gui_timer = qemu_new_timer(rt_clock, gui_update, NULL); + qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock)); + + polling_timer = qemu_new_timer(rt_clock, polling_handler, NULL); + qemu_mod_timer(polling_timer, qemu_get_clock(rt_clock)); + +#ifdef CONFIG_GDBSTUB + if (use_gdbstub) { + if (gdbserver_start(gdbstub_port) < 0) { + fprintf(stderr, "Could not open gdbserver socket on port %d\n", + gdbstub_port); + exit(1); + } else { + printf("Waiting gdb connection on port %d\n", gdbstub_port); + } + } else +#endif + if (loadvm) + qemu_loadvm(loadvm); + + { + /* XXX: simplify init */ + if (start_emulation) { + vm_start(); + } + } + main_loop(); + quit_timers(); + return 0; +} diff --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h new file mode 100644 index 0000000000..0e1cb92030 --- /dev/null +++ b/tools/ioemu/vl.h @@ -0,0 +1,786 @@ +/* + * QEMU System Emulator header + * + * Copyright (c) 2003 Fabrice Bellard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef VL_H +#define VL_H + +/* we put basic includes here to avoid repeating them in device drivers */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#ifdef _WIN32 +#define lseek _lseeki64 +#define ENOTSUP 4096 +/* XXX: find 64 bit version */ +#define ftruncate chsize + +static inline char *realpath(const char *path, char *resolved_path) +{ + _fullpath(resolved_path, path, _MAX_PATH); + return resolved_path; +} +#endif + +#ifdef QEMU_TOOL + +/* we use QEMU_TOOL in the command line tools which do not depend on + the target CPU type */ +#include "config-host.h" +#include +#include "osdep.h" +#include "bswap.h" + +#else + +#include "cpu.h" + +#endif /* !defined(QEMU_TOOL) */ + +#ifndef glue +#define xglue(x, y) x ## y +#define glue(x, y) xglue(x, y) +#define stringify(s) tostring(s) +#define tostring(s) #s +#endif + +/* vl.c */ +uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c); + +void hw_error(const char *fmt, ...); + +int get_image_size(const char *filename); +int load_image(const char *filename, uint8_t *addr); +extern const char *bios_dir; + +void pstrcpy(char *buf, int buf_size, const char *str); +char *pstrcat(char *buf, int buf_size, const char *s); +int strstart(const char *str, const char *val, const char **ptr); + +extern int vm_running; + +typedef void VMStopHandler(void *opaque, int reason); + +int qemu_add_vm_stop_handler(VMStopHandler *cb, void *opaque); +void qemu_del_vm_stop_handler(VMStopHandler *cb, void *opaque); + +void vm_start(void); +void vm_stop(int reason); + +typedef void QEMUResetHandler(void *opaque); + +void qemu_register_reset(QEMUResetHandler *func, void *opaque); +void qemu_system_reset_request(void); +void qemu_system_shutdown_request(void); + +void main_loop_wait(int timeout); + +extern int audio_enabled; +extern int sb16_enabled; +extern int adlib_enabled; +extern int gus_enabled; +extern int ram_size; +extern int bios_size; +extern int rtc_utc; +extern int cirrus_vga_enabled; +extern int graphic_width; +extern int graphic_height; +extern int graphic_depth; + +/* XXX: make it dynamic */ +#if defined (TARGET_PPC) +#define BIOS_SIZE (512 * 1024) +#else +#define BIOS_SIZE ((256 + 64) * 1024) +#endif + +/* keyboard/mouse support */ + +#define MOUSE_EVENT_LBUTTON 0x01 +#define MOUSE_EVENT_RBUTTON 0x02 +#define MOUSE_EVENT_MBUTTON 0x04 + +typedef void QEMUPutKBDEvent(void *opaque, int keycode); +typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state); + +void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque); +void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque); + +void kbd_put_keycode(int keycode); +void kbd_mouse_event(int dx, int dy, int dz, int buttons_state); + +/* keysym is a unicode code except for special keys (see QEMU_KEY_xxx + constants) */ +#define QEMU_KEY_ESC1(c) ((c) | 0xe100) +#define QEMU_KEY_BACKSPACE 0x007f +#define QEMU_KEY_UP QEMU_KEY_ESC1('A') +#define QEMU_KEY_DOWN QEMU_KEY_ESC1('B') +#define QEMU_KEY_RIGHT QEMU_KEY_ESC1('C') +#define QEMU_KEY_LEFT QEMU_KEY_ESC1('D') +#define QEMU_KEY_HOME QEMU_KEY_ESC1(1) +#define QEMU_KEY_END QEMU_KEY_ESC1(4) +#define QEMU_KEY_PAGEUP QEMU_KEY_ESC1(5) +#define QEMU_KEY_PAGEDOWN QEMU_KEY_ESC1(6) +#define QEMU_KEY_DELETE QEMU_KEY_ESC1(3) + +#define QEMU_KEY_CTRL_UP 0xe400 +#define QEMU_KEY_CTRL_DOWN 0xe401 +#define QEMU_KEY_CTRL_LEFT 0xe402 +#define QEMU_KEY_CTRL_RIGHT 0xe403 +#define QEMU_KEY_CTRL_HOME 0xe404 +#define QEMU_KEY_CTRL_END 0xe405 +#define QEMU_KEY_CTRL_PAGEUP 0xe406 +#define QEMU_KEY_CTRL_PAGEDOWN 0xe407 + +void kbd_put_keysym(int keysym); + +/* async I/O support */ + +typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size); +typedef int IOCanRWHandler(void *opaque); + +int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read, + IOReadHandler *fd_read, void *opaque); +void qemu_del_fd_read_handler(int fd); + +/* character device */ + +#define CHR_EVENT_BREAK 0 /* serial break char */ +#define CHR_EVENT_FOCUS 1 /* focus to this terminal (modal input needed) */ + +typedef void IOEventHandler(void *opaque, int event); + +typedef struct CharDriverState { + int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len); + void (*chr_add_read_handler)(struct CharDriverState *s, + IOCanRWHandler *fd_can_read, + IOReadHandler *fd_read, void *opaque); + IOEventHandler *chr_event; + void (*chr_send_event)(struct CharDriverState *chr, int event); + void *opaque; +} CharDriverState; + +void qemu_chr_printf(CharDriverState *s, const char *fmt, ...); +int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len); +void qemu_chr_send_event(CharDriverState *s, int event); +void qemu_chr_add_read_handler(CharDriverState *s, + IOCanRWHandler *fd_can_read, + IOReadHandler *fd_read, void *opaque); +void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event); + +/* consoles */ + +typedef struct DisplayState DisplayState; +typedef struct TextConsole TextConsole; + +extern TextConsole *vga_console; + +TextConsole *graphic_console_init(DisplayState *ds); +int is_active_console(TextConsole *s); +CharDriverState *text_console_init(DisplayState *ds); +void console_select(unsigned int index); + +/* serial ports */ + +#define MAX_SERIAL_PORTS 4 + +extern CharDriverState *serial_hds[MAX_SERIAL_PORTS]; + +/* network redirectors support */ + +#define MAX_NICS 8 + +typedef struct NetDriverState { + int index; /* index number in QEMU */ + uint8_t macaddr[6]; + char ifname[16]; + void (*send_packet)(struct NetDriverState *nd, + const uint8_t *buf, int size); + void (*add_read_packet)(struct NetDriverState *nd, + IOCanRWHandler *fd_can_read, + IOReadHandler *fd_read, void *opaque); + /* tun specific data */ + int fd; + /* slirp specific data */ +} NetDriverState; + +extern int nb_nics; +extern NetDriverState nd_table[MAX_NICS]; + +void qemu_send_packet(NetDriverState *nd, const uint8_t *buf, int size); +void qemu_add_read_packet(NetDriverState *nd, IOCanRWHandler *fd_can_read, + IOReadHandler *fd_read, void *opaque); + +/* timers */ + +typedef struct QEMUClock QEMUClock; +typedef struct QEMUTimer QEMUTimer; +typedef void QEMUTimerCB(void *opaque); + +/* The real time clock should be used only for stuff which does not + change the virtual machine state, as it is run even if the virtual + machine is stopped. The real time clock has a frequency of 1000 + Hz. */ +extern QEMUClock *rt_clock; + +/* Rge virtual clock is only run during the emulation. It is stopped + when the virtual machine is stopped. Virtual timers use a high + precision clock, usually cpu cycles (use ticks_per_sec). */ +extern QEMUClock *vm_clock; + +int64_t qemu_get_clock(QEMUClock *clock); + +QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque); +void qemu_free_timer(QEMUTimer *ts); +void qemu_del_timer(QEMUTimer *ts); +void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time); +int qemu_timer_pending(QEMUTimer *ts); + +extern int64_t ticks_per_sec; +extern int pit_min_timer_count; + +void cpu_enable_ticks(void); +void cpu_disable_ticks(void); + +/* VM Load/Save */ + +typedef FILE QEMUFile; + +void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size); +void qemu_put_byte(QEMUFile *f, int v); +void qemu_put_be16(QEMUFile *f, unsigned int v); +void qemu_put_be32(QEMUFile *f, unsigned int v); +void qemu_put_be64(QEMUFile *f, uint64_t v); +int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size); +int qemu_get_byte(QEMUFile *f); +unsigned int qemu_get_be16(QEMUFile *f); +unsigned int qemu_get_be32(QEMUFile *f); +uint64_t qemu_get_be64(QEMUFile *f); + +static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv) +{ + qemu_put_be64(f, *pv); +} + +static inline void qemu_put_be32s(QEMUFile *f, const uint32_t *pv) +{ + qemu_put_be32(f, *pv); +} + +static inline void qemu_put_be16s(QEMUFile *f, const uint16_t *pv) +{ + qemu_put_be16(f, *pv); +} + +static inline void qemu_put_8s(QEMUFile *f, const uint8_t *pv) +{ + qemu_put_byte(f, *pv); +} + +static inline void qemu_get_be64s(QEMUFile *f, uint64_t *pv) +{ + *pv = qemu_get_be64(f); +} + +static inline void qemu_get_be32s(QEMUFile *f, uint32_t *pv) +{ + *pv = qemu_get_be32(f); +} + +static inline void qemu_get_be16s(QEMUFile *f, uint16_t *pv) +{ + *pv = qemu_get_be16(f); +} + +static inline void qemu_get_8s(QEMUFile *f, uint8_t *pv) +{ + *pv = qemu_get_byte(f); +} + +int64_t qemu_ftell(QEMUFile *f); +int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence); + +typedef void SaveStateHandler(QEMUFile *f, void *opaque); +typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id); + +int qemu_loadvm(const char *filename); +int qemu_savevm(const char *filename); +int register_savevm(const char *idstr, + int instance_id, + int version_id, + SaveStateHandler *save_state, + LoadStateHandler *load_state, + void *opaque); +void qemu_get_timer(QEMUFile *f, QEMUTimer *ts); +void qemu_put_timer(QEMUFile *f, QEMUTimer *ts); + +/* block.c */ +typedef struct BlockDriverState BlockDriverState; +typedef struct BlockDriver BlockDriver; + +extern BlockDriver bdrv_raw; +extern BlockDriver bdrv_cow; +extern BlockDriver bdrv_qcow; +extern BlockDriver bdrv_vmdk; +extern BlockDriver bdrv_cloop; + +void bdrv_init(void); +BlockDriver *bdrv_find_format(const char *format_name); +int bdrv_create(BlockDriver *drv, + const char *filename, int64_t size_in_sectors, + const char *backing_file, int flags); +BlockDriverState *bdrv_new(const char *device_name); +void bdrv_delete(BlockDriverState *bs); +int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot); +int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot, + BlockDriver *drv); +void bdrv_close(BlockDriverState *bs); +int bdrv_read(BlockDriverState *bs, int64_t sector_num, + uint8_t *buf, int nb_sectors); +int bdrv_write(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf, int nb_sectors); +void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr); +int bdrv_commit(BlockDriverState *bs); +void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size); + +#define BDRV_TYPE_HD 0 +#define BDRV_TYPE_CDROM 1 +#define BDRV_TYPE_FLOPPY 2 + +void bdrv_set_geometry_hint(BlockDriverState *bs, + int cyls, int heads, int secs); +void bdrv_set_type_hint(BlockDriverState *bs, int type); +void bdrv_get_geometry_hint(BlockDriverState *bs, + int *pcyls, int *pheads, int *psecs); +int bdrv_get_type_hint(BlockDriverState *bs); +int bdrv_is_removable(BlockDriverState *bs); +int bdrv_is_read_only(BlockDriverState *bs); +int bdrv_is_inserted(BlockDriverState *bs); +int bdrv_is_locked(BlockDriverState *bs); +void bdrv_set_locked(BlockDriverState *bs, int locked); +void bdrv_set_change_cb(BlockDriverState *bs, + void (*change_cb)(void *opaque), void *opaque); +void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size); +void bdrv_info(void); +BlockDriverState *bdrv_find(const char *name); +void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque); +int bdrv_is_encrypted(BlockDriverState *bs); +int bdrv_set_key(BlockDriverState *bs, const char *key); +void bdrv_iterate_format(void (*it)(void *opaque, const char *name), + void *opaque); +const char *bdrv_get_device_name(BlockDriverState *bs); + +int qcow_get_cluster_size(BlockDriverState *bs); +int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num, + const uint8_t *buf); + +#ifndef QEMU_TOOL +/* ISA bus */ + +extern target_phys_addr_t isa_mem_base; + +typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data); +typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address); + +int register_ioport_read(int start, int length, int size, + IOPortReadFunc *func, void *opaque); +int register_ioport_write(int start, int length, int size, + IOPortWriteFunc *func, void *opaque); +void isa_unassign_ioport(int start, int length); + +/* PCI bus */ + +extern int pci_enabled; + +extern target_phys_addr_t pci_mem_base; + +typedef struct PCIBus PCIBus; +typedef struct PCIDevice PCIDevice; + +typedef void PCIConfigWriteFunc(PCIDevice *pci_dev, + uint32_t address, uint32_t data, int len); +typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev, + uint32_t address, int len); +typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num, + uint32_t addr, uint32_t size, int type); + +#define PCI_ADDRESS_SPACE_MEM 0x00 +#define PCI_ADDRESS_SPACE_IO 0x01 +#define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08 + +typedef struct PCIIORegion { + uint32_t addr; /* current PCI mapping address. -1 means not mapped */ + uint32_t size; + uint8_t type; + PCIMapIORegionFunc *map_func; +} PCIIORegion; + +#define PCI_ROM_SLOT 6 +#define PCI_NUM_REGIONS 7 +struct PCIDevice { + /* PCI config space */ + uint8_t config[256]; + + /* the following fields are read only */ + PCIBus *bus; + int devfn; + char name[64]; + PCIIORegion io_regions[PCI_NUM_REGIONS]; + + /* do not access the following fields */ + PCIConfigReadFunc *config_read; + PCIConfigWriteFunc *config_write; + int irq_index; +}; + +PCIDevice *pci_register_device(PCIBus *bus, const char *name, + int instance_size, int devfn, + PCIConfigReadFunc *config_read, + PCIConfigWriteFunc *config_write); + +void pci_register_io_region(PCIDevice *pci_dev, int region_num, + uint32_t size, int type, + PCIMapIORegionFunc *map_func); + +void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level); + +uint32_t pci_default_read_config(PCIDevice *d, + uint32_t address, int len); +void pci_default_write_config(PCIDevice *d, + uint32_t address, uint32_t val, int len); +void generic_pci_save(QEMUFile* f, void *opaque); +int generic_pci_load(QEMUFile* f, void *opaque, int version_id); + +extern struct PIIX3State *piix3_state; + +PCIBus *i440fx_init(void); +void piix3_init(PCIBus *bus); +void pci_bios_init(void); +void pci_info(void); + +/* temporary: will be moved in platform specific file */ +PCIBus *pci_prep_init(void); +struct openpic_t; +void pci_pmac_set_openpic(PCIBus *bus, struct openpic_t *openpic); +PCIBus *pci_pmac_init(void); + +/* openpic.c */ +typedef struct openpic_t openpic_t; +void openpic_set_irq (openpic_t *opp, int n_IRQ, int level); +openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus); + +/* vga.c */ + +#define VGA_RAM_SIZE (4096 * 1024) + +struct DisplayState { + uint8_t *data; + int linesize; + int depth; + int width; + int height; + void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h); + void (*dpy_resize)(struct DisplayState *s, int w, int h); + void (*dpy_refresh)(struct DisplayState *s); +}; + +static inline void dpy_update(DisplayState *s, int x, int y, int w, int h) +{ + s->dpy_update(s, x, y, w, h); +} + +static inline void dpy_resize(DisplayState *s, int w, int h) +{ + s->dpy_resize(s, w, h); +} + +int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, + unsigned long vga_ram_offset, int vga_ram_size); +void vga_update_display(void); +void vga_invalidate_display(void); +void vga_screen_dump(const char *filename); + +/* vnc.c */ +void vnc_display_init(DisplayState *ds, int useAlsoSDL); + +/* cirrus_vga.c */ +void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, + unsigned long vga_ram_offset, int vga_ram_size); +void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base, + unsigned long vga_ram_offset, int vga_ram_size); + +/* sdl.c */ +void sdl_display_init(DisplayState *ds, int full_screen); + +/* ide.c */ +#define MAX_DISKS 4 + +extern BlockDriverState *bs_table[MAX_DISKS]; + +void isa_ide_init(int iobase, int iobase2, int irq, + BlockDriverState *hd0, BlockDriverState *hd1); +void pci_ide_init(PCIBus *bus, BlockDriverState **hd_table); +void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table); +int pmac_ide_init (BlockDriverState **hd_table, + openpic_t *openpic, int irq); + +/* sb16.c */ +void SB16_init (void); + +/* adlib.c */ +void Adlib_init (void); + +/* gus.c */ +void GUS_init (void); + +/* dma.c */ +typedef int (*DMA_transfer_handler) (void *opaque, int nchan, int pos, int size); +int DMA_get_channel_mode (int nchan); +int DMA_read_memory (int nchan, void *buf, int pos, int size); +int DMA_write_memory (int nchan, void *buf, int pos, int size); +void DMA_hold_DREQ (int nchan); +void DMA_release_DREQ (int nchan); +void DMA_schedule(int nchan); +void DMA_run (void); +void DMA_init (int high_page_enable); +void DMA_register_channel (int nchan, + DMA_transfer_handler transfer_handler, + void *opaque); +/* fdc.c */ +#define MAX_FD 2 +extern BlockDriverState *fd_table[MAX_FD]; + +typedef struct fdctrl_t fdctrl_t; + +fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped, + uint32_t io_base, + BlockDriverState **fds); +int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num); + +/* ne2000.c */ + +void isa_ne2000_init(int base, int irq, NetDriverState *nd); +void pci_ne2000_init(PCIBus *bus, NetDriverState *nd); + +/* pckbd.c */ + +void kbd_init(void); +extern const char* keyboard_layout; + +/* mc146818rtc.c */ + +typedef struct RTCState RTCState; + +RTCState *rtc_init(int base, int irq); +void rtc_set_memory(RTCState *s, int addr, int val); +void rtc_set_date(RTCState *s, const struct tm *tm); + +/* serial.c */ + +typedef struct SerialState SerialState; +SerialState *serial_init(int base, int irq, CharDriverState *chr); + +/* i8259.c */ + +void pic_set_irq(int irq, int level); +void pic_init(void); +uint32_t pic_intack_read(CPUState *env); +void pic_info(void); +void irq_info(void); +int pic_irq2vec(int irq); + +/* i8254.c */ + +#define PIT_FREQ 1193182 + +typedef struct PITState PITState; + +PITState *pit_init(int base, int irq); +void pit_set_gate(PITState *pit, int channel, int val); +int pit_get_gate(PITState *pit, int channel); +int pit_get_out(PITState *pit, int channel, int64_t current_time); + +/* pc.c */ +void pc_init(int ram_size, int vga_ram_size, int boot_device, + DisplayState *ds, const char **fd_filename, int snapshot, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename); + +/* ppc.c */ +void ppc_init (int ram_size, int vga_ram_size, int boot_device, + DisplayState *ds, const char **fd_filename, int snapshot, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename); +void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device, + DisplayState *ds, const char **fd_filename, int snapshot, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename); +void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device, + DisplayState *ds, const char **fd_filename, int snapshot, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename); +#ifdef TARGET_PPC +ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq); +#endif +void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val); + +extern CPUWriteMemoryFunc *PPC_io_write[]; +extern CPUReadMemoryFunc *PPC_io_read[]; +extern int prep_enabled; + +/* sun4m.c */ +void sun4m_init(int ram_size, int vga_ram_size, int boot_device, + DisplayState *ds, const char **fd_filename, int snapshot, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename); + +/* iommu.c */ +void iommu_init(uint32_t addr); +uint32_t iommu_translate(uint32_t addr); + +/* lance.c */ +void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr); + +/* tcx.c */ +void tcx_init(DisplayState *ds, uint32_t addr); + +/* sched.c */ +void sched_init(); + +/* magic-load.c */ +void magic_init(const char *kfn, int kloadaddr, uint32_t addr); + +/* timer.c */ +void timer_init(uint32_t addr, int irq); + +/* NVRAM helpers */ +#include "hw/m48t59.h" + +void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value); +uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr); +void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value); +uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr); +void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value); +uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr); +void NVRAM_set_string (m48t59_t *nvram, uint32_t addr, + const unsigned char *str, uint32_t max); +int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max); +void NVRAM_set_crc (m48t59_t *nvram, uint32_t addr, + uint32_t start, uint32_t count); +int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size, + const unsigned char *arch, + uint32_t RAM_size, int boot_device, + uint32_t kernel_image, uint32_t kernel_size, + const char *cmdline, + uint32_t initrd_image, uint32_t initrd_size, + uint32_t NVRAM_image, + int width, int height, int depth); + +/* adb.c */ + +#define MAX_ADB_DEVICES 16 + +#define ADB_MAX_OUT_LEN 16 + +typedef struct ADBDevice ADBDevice; + +/* buf = NULL means polling */ +typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out, + const uint8_t *buf, int len); +typedef int ADBDeviceReset(ADBDevice *d); + +struct ADBDevice { + struct ADBBusState *bus; + int devaddr; + int handler; + ADBDeviceRequest *devreq; + ADBDeviceReset *devreset; + void *opaque; +}; + +typedef struct ADBBusState { + ADBDevice devices[MAX_ADB_DEVICES]; + int nb_devices; + int poll_index; +} ADBBusState; + +int adb_request(ADBBusState *s, uint8_t *buf_out, + const uint8_t *buf, int len); +int adb_poll(ADBBusState *s, uint8_t *buf_out); + +ADBDevice *adb_register_device(ADBBusState *s, int devaddr, + ADBDeviceRequest *devreq, + ADBDeviceReset *devreset, + void *opaque); +void adb_kbd_init(ADBBusState *bus); +void adb_mouse_init(ADBBusState *bus); + +/* cuda.c */ + +extern ADBBusState adb_bus; +int cuda_init(openpic_t *openpic, int irq); + +#endif /* defined(QEMU_TOOL) */ + +/* monitor.c */ +void monitor_init(CharDriverState *hd, int show_banner); +void term_puts(const char *str); +void term_vprintf(const char *fmt, va_list ap); +void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2))); +void term_flush(void); +void term_print_help(void); + +/* readline.c */ +typedef void ReadLineFunc(void *opaque, const char *str); + +extern int completion_index; +void add_completion(const char *str); +void readline_handle_byte(int ch); +void readline_find_completion(const char *cmdline); +const char *readline_get_history(unsigned int index); +void readline_start(const char *prompt, int is_password, + ReadLineFunc *readline_func, void *opaque); + +/* gdbstub.c */ + +#define DEFAULT_GDBSTUB_PORT 1234 + +int gdbserver_start(int port); + +#endif /* VL_H */ diff --git a/tools/ioemu/vnc.c b/tools/ioemu/vnc.c new file mode 100644 index 0000000000..06601f3f09 --- /dev/null +++ b/tools/ioemu/vnc.c @@ -0,0 +1,501 @@ +/* + * QEMU VNC display driver (uses LibVNCServer, based on QEMU SDL driver) + * + * Copyright (c) 2003,2004 Fabrice Bellard, Matthew Mastracci, + * Johannes E. Schindelin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "vl.h" + +#include + +/* keyboard stuff */ +#include +#include "keysym_adapter_vnc.h" +#include "keyboard_rdesktop.c" + + +#ifndef _WIN32 +#include +#endif + +static rfbScreenInfoPtr screen; +static DisplayState* ds_sdl=0; +static void* kbd_layout=0; // TODO: move into rfbClient + +/* mouse stuff */ + +typedef struct mouse_magic_t { + /* When calibrating, mouse_calibration contains a copy of the + * current frame buffer. After a simulated mouse movement, the + * update function only gets (0,y1,width,y2) as bounding box + * of the changed region, so we refine that with the help of + * this copy, and then update the copy. */ + char* calibration; + /* Mouse handling using VNC used to be wrong, because if moving the + * mouse very fast, the pointer got even faster. The reason for this: + * when the mouse sends a delta of at least 4 (Windows: 3) pixels, + * it is treated as if it were double the amount. I call this the + * sonic wall. */ + int sonic_wall_x; + int sonic_wall_y; + /* Unfortunately, Windows and X behave differently, when the sonic + * wall was reached in one axis, but not the other: Windows treats + * them independently. I call this orthogonal. */ + char sonic_wall_is_orthogonal; + /* last_dy contains the last delta sent on the y axis. We don't + * use the x axis (see mouse_calibration). */ + //static int last_dy=0; +} mouse_magic_t; + +mouse_magic_t* init_mouse_magic() { + mouse_magic_t* ret=(mouse_magic_t*)malloc(sizeof(mouse_magic_t)); + + ret->calibration=0; +#ifdef EXPECT_WINDOWS_GUEST + ret->sonic_wall_x=3; + ret->sonic_wall_y=3; + ret->sonic_wall_is_orthogonal=1; +#else + ret->sonic_wall_x=4; + ret->sonic_wall_y=4; + ret->sonic_wall_is_orthogonal=0; +#endif + return ret; +} + +static void vnc_save(QEMUFile* f,void* opaque) +{ + mouse_magic_t* s=(mouse_magic_t*)opaque; + + qemu_put_be32s(f, &s->sonic_wall_x); + qemu_put_be32s(f, &s->sonic_wall_y); + qemu_put_8s(f, &s->sonic_wall_is_orthogonal); +} + +static int vnc_load(QEMUFile* f,void* opaque,int version_id) +{ + mouse_magic_t* s=(mouse_magic_t*)opaque; + + if (version_id != 1) + return -EINVAL; + + qemu_get_be32s(f, &s->sonic_wall_x); + qemu_get_be32s(f, &s->sonic_wall_y); + qemu_get_8s(f, &s->sonic_wall_is_orthogonal); + + return 0; +} + +static mouse_magic_t* mouse_magic; + +typedef struct { + int x,y,w,h; +} rectangle_t; +/* In order to calibrate the mouse, we have to know about the bounding boxes + * of the last changes. */ +static rectangle_t last_update, before_update; +static int updates_since_mouse=0; + +static int mouse_x,mouse_y; +static int new_mouse_x,new_mouse_y,new_mouse_z,new_mouse_buttons; + +static void init_mouse(int initial_x,int initial_y) { + mouse_x=new_mouse_x=initial_x; + mouse_y=new_mouse_y=initial_y; + new_mouse_z=new_mouse_buttons=0; + mouse_magic->calibration = 0; +} + +static void mouse_refresh() { + int dx=0,dy=0,dz=new_mouse_z; + static int counter=1; + + counter++; + if(!mouse_magic->calibration && counter>=2) { counter=0; return; } + + dx=new_mouse_x-mouse_x; + dy=new_mouse_y-mouse_y; + + if(mouse_magic->sonic_wall_is_orthogonal) { + if(abs(dx)>=mouse_magic->sonic_wall_x) { dx/=2; mouse_x+=dx; } + if(abs(dy)>=mouse_magic->sonic_wall_y) { dy/=2; mouse_y+=dy; } + } else { + if(abs(dx)>=mouse_magic->sonic_wall_x || abs(dy)>=mouse_magic->sonic_wall_y) { + dx/=2; mouse_x+=dx; + dy/=2; mouse_y+=dy; + } + } + //fprintf(stderr,"sending mouse event %d,%d\n",dx,dy); + kbd_mouse_event(dx,dy,dz,new_mouse_buttons); + mouse_x+=dx; + mouse_y+=dy; + + updates_since_mouse=0; +} + +static int calibration_step=0; +//static int calibration_count=0; + +static void mouse_find_bounding_box_of_difference(int* x,int* y,int* w,int* h) { + int i,j,X=*x,Y=*y,W=*w,H=*h; + int bpp=screen->depth/8; + + *x=screen->width; *w=-*x; + *y=screen->height; *h=-*y; + for(i=X;ipaddedWidthInBytes; + if(memcmp(mouse_magic->calibration+offset,screen->frameBuffer+offset,bpp)) { + if(i<((*x))) { (*w)+=(*x)-i; (*x)=i; } + if(i>(*x)+(*w)) (*w)=i-(*x); + if(j<(*y)) { (*h)+=(*y)-j; (*y)=j; } + if(j>(*y)+(*h)) (*h)=j-(*y); + } + } + if(h>0) + memcpy(mouse_magic->calibration+Y*screen->paddedWidthInBytes, + screen->frameBuffer+Y*screen->paddedWidthInBytes, + H*screen->paddedWidthInBytes); +} + +static void start_mouse_calibration() { + int size = screen->height*screen->paddedWidthInBytes; + if(mouse_magic->calibration) + free(mouse_magic->calibration); + mouse_magic->calibration = malloc(size); + memcpy(mouse_magic->calibration, screen->frameBuffer, size); + calibration_step=0; + // calibration_count=-1; + //calibration_count=1000; updates_since_mouse=1; + fprintf(stderr,"Starting mouse calibration:\n"); +} + +static void stop_mouse_calibration() { + if(mouse_magic->calibration) + free(mouse_magic->calibration); + mouse_magic->calibration = 0; +} + +static void mouse_calibration_update(int x,int y,int w,int h) { + mouse_find_bounding_box_of_difference(&x,&y,&w,&h); + if(w<=0 || h<=0) + return; + last_update.x=x; + last_update.y=y; + last_update.w=w; + last_update.h=h; + updates_since_mouse++; +} + +static void mouse_calibration_refresh() { + static rectangle_t cursor; + static int x,y; + static int idle_counter; + + if(calibration_step==0) + idle_counter=0; + else { + if(updates_since_mouse==0) { + idle_counter++; + if(idle_counter>5) { + fprintf(stderr, "Calibration failed: no update for 5 cycles\n"); + stop_mouse_calibration(); + } + return; + } + if(updates_since_mouse!=1) { + fprintf(stderr,"Calibration failed: updates=%d\n",updates_since_mouse); + stop_mouse_calibration(); + return; + } + } + + if(calibration_step==0) { + x=0; y=1; + kbd_mouse_event(0,-1,0,0); + calibration_step++; + } else if(calibration_step==1) { + // find out the initial position of the cursor + cursor=last_update; + cursor.h--; + calibration_step++; + mouse_magic->sonic_wall_y=-1; + last_update=cursor; + x=0; y=2; + goto move_calibrate; + } else if(calibration_step==2) { + // find out the sonic_wall + if(last_update.y==before_update.y-2*y) { + mouse_magic->sonic_wall_y=y; + // test orthogonality + calibration_step++; + x=mouse_magic->sonic_wall_y+1; y=1; + goto move_calibrate; + } else if(last_update.y<=2) { + if(y<6) + fprintf(stderr,"Calibration failed: not enough head room!\n"); + else + fprintf(stderr,"Calibration finished.\n"); + mouse_magic->sonic_wall_x=mouse_magic->sonic_wall_y=32768; + goto stop_calibration; + } else if(last_update.y!=before_update.y-y) { + fprintf(stderr,"Calibration failed: delta=%d (expected: %d)\n",last_update.y-before_update.y,-y); + goto stop_calibration; + } else { + y++; +move_calibrate: + kbd_mouse_event(-x,-y,0,0); + before_update=last_update; + } + } else if(calibration_step==3) { + if(last_update.y==before_update.y-2) + mouse_magic->sonic_wall_is_orthogonal=0; + else if(last_update.y==before_update.y-1) + mouse_magic->sonic_wall_is_orthogonal=-1; + else + fprintf(stderr,"Calibration failed: no clue of orthogonal.\n"); + mouse_magic->sonic_wall_x=mouse_magic->sonic_wall_y; + if(last_update.x==before_update.x-mouse_magic->sonic_wall_x) + mouse_magic->sonic_wall_x++; + else if(last_update.x!=before_update.x-x*2) + fprintf(stderr,"Calibration failed: could not determine horizontal sonic wall x\n"); + fprintf(stderr,"Calibration finished\n"); +stop_calibration: + mouse_x=last_update.x; + mouse_y=last_update.y; + stop_mouse_calibration(); + } + updates_since_mouse=0; +} + +/* end of mouse stuff */ + +static void vnc_update(DisplayState *ds, int x, int y, int w, int h) +{ + if(ds_sdl) + ds_sdl->dpy_update(ds_sdl,x,y,w,h); + if(0) fprintf(stderr,"updating x=%d y=%d w=%d h=%d\n", x, y, w, h); + rfbMarkRectAsModified(screen,x,y,x+w,y+h); + if(mouse_magic->calibration) { + mouse_calibration_update(x,y,w,h); + } +} + +#include +extern SDL_PixelFormat* sdl_get_format(); + +static void vnc_resize(DisplayState *ds, int w, int h) +{ + int depth = screen->bitsPerPixel; + rfbClientIteratorPtr iter; + rfbClientPtr cl; + + if(w==screen->width && h==screen->height) + return; + + if(ds_sdl) { + SDL_PixelFormat* sdl_format; + ds_sdl->dpy_resize(ds_sdl,w,h); + ds->data = ds_sdl->data; + ds->linesize = screen->paddedWidthInBytes = ds_sdl->linesize; + screen->serverFormat.bitsPerPixel = screen->serverFormat.depth + = screen->bitsPerPixel = depth = ds->depth = ds_sdl->depth; + w = ds->width = ds_sdl->width; + h = ds->height = ds_sdl->height; + sdl_format=sdl_get_format(); + if(sdl_format->palette==0) { + screen->serverFormat.trueColour=TRUE; + screen->serverFormat.redShift=sdl_format->Rshift; + screen->serverFormat.greenShift=sdl_format->Gshift; + screen->serverFormat.blueShift=sdl_format->Bshift; + screen->serverFormat.redMax=sdl_format->Rmask>>screen->serverFormat.redShift; + screen->serverFormat.greenMax=sdl_format->Gmask>>screen->serverFormat.greenShift; + screen->serverFormat.blueMax=sdl_format->Bmask>>screen->serverFormat.blueShift; + } else { + rfbColourMap* cmap=&(screen->colourMap); + int i; + screen->serverFormat.trueColour=FALSE; + cmap->is16=FALSE; + cmap->count=sdl_format->palette->ncolors; + if(cmap->data.bytes==0) + cmap->data.bytes=malloc(256*3); + for(i=0;icount;i++) { + cmap->data.bytes[3*i+0]=sdl_format->palette->colors[i].r; + cmap->data.bytes[3*i+1]=sdl_format->palette->colors[i].g; + cmap->data.bytes[3*i+2]=sdl_format->palette->colors[i].b; + } + } + } else { + ds->data = (unsigned char*)realloc(ds->data, w*h*depth/8); + ds->linesize = screen->paddedWidthInBytes = w*2; + ds->width = w; + ds->height = h; + ds->depth = depth; + screen->paddedWidthInBytes = w*depth/8; + } + screen->frameBuffer = ds->data; + + screen->width = w; + screen->height = h; + + iter=rfbGetClientIterator(screen); + while((cl=rfbClientIteratorNext(iter))) + if(cl->useNewFBSize) + cl->newFBSizePending = TRUE; + else + rfbLog("Warning: Client %s does not support NewFBSize!\n",cl->host); + rfbReleaseClientIterator(iter); + + if(mouse_magic->calibration) { + fprintf(stderr,"Warning: mouse calibration interrupted by video mode change\n"); + stop_mouse_calibration(); + } + init_mouse(w/2,h/2); +} + +static void vnc_process_key(rfbBool down, rfbKeySym keySym, rfbClientPtr cl) +{ + static int magic=0; // Ctrl+Alt starts calibration + + if(is_active_console(vga_console)) { + WORD keycode=keysym2scancode(kbd_layout, keySym); + if(keycode>=0x80) + keycode=(keycode<<8)^0x80e0; + while(keycode!=0) { + kbd_put_keycode((keycode&0xff)|(down?0:0x80)); + keycode>>=8; + } + } else if(down) { + kbd_put_keysym(keySym); + } + if(down) { + if(keySym==XK_Control_L) + magic|=1; + else if(keySym==XK_Alt_L) + magic|=2; + } else { + if((magic&3)==3) { + switch(keySym) { + case XK_Control_L: + magic&=~1; + break; + case XK_Alt_L: + magic&=~2; + break; + case XK_m: + magic=0; + start_mouse_calibration(); + break; + case XK_1 ... XK_9: + magic=0; + fprintf(stderr,"switch to %d\n",keySym-XK_1); + console_select(keySym - XK_1); + if (is_active_console(vga_console)) { + /* tell the vga console to redisplay itself */ + vga_invalidate_display(); + vnc_update(0,0,0,screen->width,screen->height); + } + break; + } + } + } +} + +static void vnc_process_mouse(int buttonMask, int x, int y, rfbClientPtr cl) +{ + new_mouse_x=x; new_mouse_y=y; new_mouse_buttons=0; + if(buttonMask&1) new_mouse_buttons|=MOUSE_EVENT_LBUTTON; + if(buttonMask&2) new_mouse_buttons|=MOUSE_EVENT_MBUTTON; + if(buttonMask&4) new_mouse_buttons|=MOUSE_EVENT_RBUTTON; + if(buttonMask&8) new_mouse_z--; + if(buttonMask&16) new_mouse_z++; +} + + static void vnc_refresh(DisplayState *ds) { + if(ds_sdl) + ds_sdl->dpy_refresh(ds_sdl); + else + vga_update_display(); + rfbProcessEvents(screen,0); + if(mouse_magic->calibration) { + mouse_calibration_refresh(); + } else { + mouse_refresh(); + } + } + +static void vnc_cleanup(void) +{ + rfbScreenCleanup(screen); +} + +void vnc_display_init(DisplayState *ds, int useAlsoSDL) +{ + if(!keyboard_layout) { + fprintf(stderr, "No keyboard language specified\n"); + exit(1); + } + + kbd_layout=init_keyboard_layout(keyboard_layout); + if(!kbd_layout) { + fprintf(stderr, "Could not initialize keyboard\n"); + exit(1); + } + + mouse_magic=init_mouse_magic(); + register_savevm("vnc", 0, 1, vnc_save, vnc_load, mouse_magic); + + rfbLog=rfbErr=term_printf; + screen=rfbGetScreen(0,0,0,0,5,3,2); + if(screen==0) { + fprintf(stderr, "Could not initialize VNC - exiting\n"); + exit(1); + } + + screen->serverFormat.redShift = 11; + screen->serverFormat.greenShift = 5; + screen->serverFormat.blueShift = 0; + screen->serverFormat.redMax = 31; + screen->serverFormat.greenMax = 63; + screen->serverFormat.blueMax = 31; + + if(useAlsoSDL) { + ds_sdl=(DisplayState*)malloc(sizeof(DisplayState)); + sdl_display_init(ds_sdl,0); + screen->frameBuffer = ds_sdl->data; + } else + screen->frameBuffer = malloc(640*400*2); + + screen->desktopName = "QEMU/VNC"; + screen->cursor = 0; + screen->kbdAddEvent = vnc_process_key; + screen->ptrAddEvent = vnc_process_mouse; + rfbInitServer(screen); + + vnc_resize(ds,640,400); + + ds->dpy_update = vnc_update; + ds->dpy_resize = vnc_resize; + ds->dpy_refresh = vnc_refresh; + + atexit(vnc_cleanup); +} + -- 2.30.2